I have a fairly common requirement to enable user-defined sorting, for example using a querystring like so:
?page=2&sort=name&desc=true
This isn’t really catered for using LINQ, due to type-safety (you need to use an expression based on a property of your object to do sorting). To enable dynamic sorting on an IQueryable object, try this:
private static readonly MethodInfo OrderByMethod = typeof(Queryable).GetMethods() .Where(method => method.Name == "OrderBy") .Where(method => method.GetParameters().Length == 2) .Single(); private static readonly MethodInfo OrderByDescendingMethod = typeof(Queryable).GetMethods() .Where(method => method.Name == "OrderByDescending") .Where(method => method.GetParameters().Length == 2) .Single(); public static IQueryable DynamicOrderBy(this IQueryable source, string sortBy, bool sortDescending = false) { if (string.IsNullOrWhiteSpace(sortBy)) return source; if (sortBy.Contains(',')) { foreach (var sort in sortBy.Split(',')) { source = source.DynamicOrderBy(sort, sortDescending); } return source; } else { var type = typeof(TSource); var parameter = Expression.Parameter(type, sortBy); var propertyRef = Expression.Property(parameter, sortBy); var lambda = Expression.Lambda(propertyRef, new[] { parameter }); MethodInfo genericMethod = (sortDescending ? OrderByDescendingMethod : OrderByMethod) .MakeGenericMethod(new[] { typeof(TSource), propertyRef.Type }); object ret = genericMethod.Invoke(null, new object[] { source, lambda }); return (IQueryable)ret; } }
Putting this in your code allows you to write something like this:
IQueryable data = GetData(); var sortedByNameDescending = data.DynamicOrderBy("Name", true);