Skip to content

Instantly share code, notes, and snippets.

@worldspawn
Last active February 29, 2016 05:11
Show Gist options
  • Save worldspawn/c054ddcda0bcdf6b45fe to your computer and use it in GitHub Desktop.
Save worldspawn/c054ddcda0bcdf6b45fe to your computer and use it in GitHub Desktop.
Order a queryable based on a string input. "Members" can be a value like: "Name, Company.Type desc, Company.Name". Handles nested property references, ascending/descending and nullable/nonnullable targets.
private IQueryable<T> Order<T>(IQueryable<T> list, string members)
{
var param = Expression.Parameter(list.ElementType, "r");
bool thenMode = false;
foreach (var member in members.Split(','))
{
MemberExpression memberExpression = null;
var chop = member.Split(' ');
foreach (var memberPart in chop[0].Split('.'))
{
memberExpression = Expression.PropertyOrField((Expression)memberExpression ?? param, memberPart);
}
bool sortDescending = false;
if (chop.Length > 1)
{
sortDescending = chop[1].IndexOf("desc", StringComparison.InvariantCultureIgnoreCase) > -1;
}
string command;
if (thenMode)
{
command = sortDescending ? "ThenByDescending" : "ThenBy";
}
else
{
command = sortDescending ? "OrderByDescending" : "OrderBy";
}
var exp = Expression.Lambda(memberExpression, param);
var resultExpression = Expression.Call(typeof(Queryable), command, new[] { typeof(T), memberExpression.Type }, list.Expression, Expression.Quote(exp));
list = list.Provider.CreateQuery<T>(resultExpression);
thenMode = true;
}
return list;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment