using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Umbraco.Core.Dynamics { /// /// Extension methods for IQueryable /// /// /// NOTE: Ordering code taken from: http://stackoverflow.com/questions/41244/dynamic-linq-orderby-on-ienumerablet /// /// ANOTHER NOTE: We have a bastardized version of Dynamic Linq existing at Umbraco.Web.Dynamics however it's been hacked so not /// sure we can use it for anything other than DynamicNode. /// internal static class QueryableExtensions { 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 = 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; } } }