Skip to content

Instantly share code, notes, and snippets.

@neoGeneva
Created February 21, 2012 20:55
Show Gist options
  • Save neoGeneva/1878868 to your computer and use it in GitHub Desktop.
Save neoGeneva/1878868 to your computer and use it in GitHub Desktop.
An OrderBy extension method for IQueryable that takes string
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortExpression)
{
if (source == null)
throw new ArgumentNullException("source", "source is null.");
if (string.IsNullOrEmpty(sortExpression))
throw new ArgumentException("sortExpression is null or empty.", "sortExpression");
var parts = sortExpression.Split(' ');
var isDescending = false;
var propertyName = "";
var tType = typeof(T);
if (parts.Length > 0 && parts[0] != "")
{
propertyName = parts[0];
if (parts.Length > 1)
{
isDescending = parts[1].ToLower().Contains("esc");
}
PropertyInfo prop = tType.GetProperty(propertyName);
if (prop == null)
{
throw new ArgumentException(string.Format("No property '{0}' on type '{1}'", propertyName, tType.Name));
}
var funcType = typeof(Func<,>)
.MakeGenericType(tType, prop.PropertyType);
var lambdaBuilder = typeof(Expression)
.GetMethods()
.First(x => x.Name == "Lambda" && x.ContainsGenericParameters && x.GetParameters().Length == 2)
.MakeGenericMethod(funcType);
var parameter = Expression.Parameter(tType);
var propExpress = Expression.Property(parameter, prop);
var sortLambda = lambdaBuilder
.Invoke(null, new object[] { propExpress, new ParameterExpression[] { parameter } });
var sorter = typeof(Queryable)
.GetMethods()
.FirstOrDefault(x => x.Name == (isDescending ? "OrderByDescending" : "OrderBy") && x.GetParameters().Length == 2)
.MakeGenericMethod(new[] { tType, prop.PropertyType });
return (IQueryable<T>)sorter
.Invoke(null, new object[] { source, sortLambda });
}
return source;
}
@DominicArchual
Copy link

Thanks for the great code. It needed to be written 👍

@peter-bruderlin
Copy link

I'd like to add that this is a beautiful piece of heavy voodoo that helped me genericise server-side pagination.
Thank you!

@BharateshChivate
Copy link

How to change this code to support sorting for multiple columns. Eg: a.OrderBy(x).ThenBy(y).ThenByDesc(z).

@neoGeneva
Copy link
Author

@BharateshChivate it wouldn't be too hard to create a "ThenBy" equivalent, the thing that would need to change is on line 47, finding the "ThenBy" or "ThenByDescending" instead of "OrderBy" and "OrderByDescending".

So personally I'm still using this in my code base, but I imagine there's nuget packages which do the same thing. I'm not sure but I think DynamicLinq by the ZZZ Projects folks would probably do the job, I've used a lot of their stuff in the past and definitely recommend them.

@BharateshChivate
Copy link

Thankyou for the reply.

Actually our sortExpression is in this format - id:asc,Name:desc.
Note: sortExpression can have multiple columns i.e., >2.

So, in this case I need to create my query like this - x.OrderBy(id).ThenByDesc(Name).

But the above code written by you works for only 1 column. I wanted to understand how to make this code work for multiple columna in sortexpression.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment