Within a generic extension method, how do I apply OrderBy to an IQueryable using a string column name?

.net c# entity-framework expression-trees linq

Question

public static IQueryable<TResult> ApplySortFilter<T, TResult>(this IQueryable<T> query, string columnName)
  where T : EntityObject
{
  var param = Expression.Parameter(typeof(T), "o");
  var body = Expression.PropertyOrField(param,columnName);

  var sortExpression = Expression.Lambda(body, param);
  return query.OrderBy(sortExpression);
}

Because sortExpression does not deduce the type for OrderBy, I must provide it at runtime in a manner similar to this:

var sortExpression = Expression.Lambda<T, TSortColumn>(body, param);

Or

return query.OrderBy<T, TSortColumn>(sortExpression);

However, as TSortColumn can only be decided at runtime, I don't believe this is viable.

Exists a method to get around this?

1
84
5/24/2012 12:41:08 PM

Accepted Answer

We carried out a similar (but not quite same) action in a LINQ to SQL project. Here is the key:

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {
    var type = typeof(T);
    var property = type.GetProperty(ordering);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExp = Expression.Lambda(propertyAccess, parameter);
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
    return source.Provider.CreateQuery<T>(resultExp);
}

We had a known class, so we didn't really use a generic, but it should work on one (I've placed the generic placeholder there).

Edit: Pass in the decreasing orderOrderByDescending substitute "OrderBy" with:

MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExp));
110
5/24/2012 2:34:40 PM

Popular Answer

Also available is Dynamic Linq.

info here zz-9 zz

Download C# here, version 16-zzz.

After that, just include the using Linq.Dynamic; this will give you access to two more extension methods.

return query.OrderBy("StringColumnName");


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow