views:

326

answers:

3

How can i make an extension method that will work like this

public static class Extensions<T>
{
    public static IQueryable<T> Sort(this IQueryable<T> query, string sortField, SortDirection direction)
    {
        // System.Type dataSourceType = query.GetType();

        //System.Type dataItemType = typeof(object);

        //if (dataSourceType.HasElementType)
        //{
        //    dataItemType = dataSourceType.GetElementType();
        //}
        //else if (dataSourceType.IsGenericType)
        //{
        //    dataItemType = dataSourceType.GetGenericArguments()[0];
        //}

        //var fieldType = dataItemType.GetProperty(sortField);
        if (direction == SortDirection.Ascending)
            return query.OrderBy(s => s.GetType().GetProperty(sortField));
        return query.OrderByDescending(s => s.GetType().GetProperty(sortField));

    }
}

Currently that says "Extension methods must be defined in a non-generic static class".

How do i do this?

+6  A: 

Change this:

public static class Extensions
{
    public static IQueryable<T> Sort<T>(this IQueryable<T> query, string sortField, SortDirection direction)
    {
      //code
    }
}

The class needs to be non-generic, just your extension method should be :)

Nick Craver
+3  A: 

Try this... (but I'm not sure it will do what you want.)

public static class Extensions
{ 
    public static IQueryable<T> Sort<T>(this IQueryable<T> query, 
                                             string sortField, 
                                             SortDirection direction) 
    { 
        if (direction == SortDirection.Ascending) 
            return query.OrderBy(s => s.GetType()
                                       .GetProperty(sortField)); 
        return query.OrderByDescending(s => s.GetType()
                                             .GetProperty(sortField)); 

    } 
} 

... The generic parameter should be on the method and not on the class. Moving it from Extensions<T> to Sort<T>( would allow you to get rid of the compiler error you are having.

As for what you are trying to do with reflection, you would be returning a PropertyInfo object for the orderby clause. This is most likely not compable with the expression tree that you want. You may want to look at Dynamic LINQ.

... this is an extract from Dynamic LINQ.

public static IQueryable OrderBy(this IQueryable source, 
                                      string ordering, 
                                      params object[] values) {
    if (source == null) throw new ArgumentNullException("source");
    if (ordering == null) throw new ArgumentNullException("ordering");
    ParameterExpression[] parameters = new ParameterExpression[] {
        Expression.Parameter(source.ElementType, "") };
    ExpressionParser parser = new ExpressionParser(parameters, 
                                                   ordering, 
                                                   values);
    IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
    Expression queryExpr = source.Expression;
    string methodAsc = "OrderBy";
    string methodDesc = "OrderByDescending";
    foreach (DynamicOrdering o in orderings) {
        queryExpr = Expression.Call(
            typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
            new Type[] { source.ElementType, o.Selector.Type },
            queryExpr, Expression.Quote(Expression.Lambda(o.Selector, 
                                                          parameters)));
        methodAsc = "ThenBy";
        methodDesc = "ThenByDescending";
    }
    return source.Provider.CreateQuery(queryExpr);
}
Matthew Whited
Thanks for the answer and the extra links... I've been trying to do dynamic linq all morning without knowing what i was really doing.Can't say i really do now, either... need to do some reading up on all of this.Thanks again!
Micah
I think we have all been there :o) ... good luck!
Matthew Whited
By the way, this piece of code here http://stackoverflow.com/questions/41244/dynamic-linq-orderby really helped too
Micah
If you go to the link above to ScottGu's blog you will see more about Dynamic LINQ
Matthew Whited
+1  A: 

The error already tells you:

Extension methods must be defined in a non-generic static class.

Simply remove the generic type argument.

public static class Extensions // no <T>
{
    // ...
}
Thomas
This won't resolve the issue, the method needs the generic parameter added as well: `Sort<T>`
Nick Craver
It resolves *one* issue, at least. And maybe it teaches someone to actually read error messages... Nah, who am I kidding.
Thomas
Don't worry... just moving the generic parameter isn't going to solve the problem he will find shortly.
Matthew Whited