Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IQueryable<T> Extension Method not working

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?

like image 449
Micah Avatar asked Apr 01 '10 18:04

Micah


3 Answers

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);
}
like image 79
Matthew Whited Avatar answered Oct 31 '22 17:10

Matthew Whited


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 :)

like image 25
Nick Craver Avatar answered Oct 31 '22 18:10

Nick Craver


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>
{
    // ...
}
like image 3
Thomas Avatar answered Oct 31 '22 17:10

Thomas