To do this without the dynamic LINQ library, you just need the code as below. This covers most common scenarios including nested properties.
To get it working with IEnumerable
public static IOrderedQueryableOrderBy (this IQueryable source, string property)
{
return ApplyOrder(source, property, "OrderBy");
}
public static IOrderedQueryableOrderByDescending (this IQueryable source, string property)
{
return ApplyOrder(source, property, "OrderByDescending");
}
public static IOrderedQueryableThenBy (this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenBy");
}
public static IOrderedQueryableThenByDescending (this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenByDescending");
}
static IOrderedQueryableApplyOrder (IQueryable source, string property, string methodName) {
string[] props = property.Split('.');
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach(string prop in props) {
// use reflection (not ComponentModel) to mirror LINQ
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] {source, lambda});
return (IOrderedQueryable)result;
}
No comments:
Post a Comment