Skip to content

Instantly share code, notes, and snippets.

@jrgcubano
Created October 28, 2014 12:54
Show Gist options
  • Save jrgcubano/a164d914032843024582 to your computer and use it in GitHub Desktop.
Save jrgcubano/a164d914032843024582 to your computer and use it in GitHub Desktop.
Order by helper with expressions and dot notation
#region Process Data (sort, group, filter, etc)
public static EnumerableQuery GroupBy(this IOrderedQueryable source, string property)
{
return ApplyGroup(source, property, "GroupBy");
}
public static IOrderedQueryable OrderBy(this IQueryable source, string property)
{
return ApplyOrder(source, property, "OrderBy");
}
public static IOrderedQueryable OrderByDescending(this IQueryable source, string property)
{
return ApplyOrder(source, property, "OrderByDescending");
}
public static IOrderedQueryable ThenBy(this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenBy");
}
public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenByDescending");
}
static IOrderedQueryable ApplyOrder(IQueryable source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = source.ElementType;
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach (string prop in props)
{
// reflection
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(source.ElementType, 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(source.ElementType, type)
.Invoke(null, new object[] { source, lambda });
return (IOrderedQueryable)result;
}
static EnumerableQuery ApplyGroup(IQueryable source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = source.ElementType;
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach (string prop in props)
{
// reflection
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(source.ElementType, 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(source.ElementType, type)
.Invoke(null, new object[] { source, lambda });
return (EnumerableQuery)result;
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment