/// <summary> /// Apply ordering to sort queryable result. /// </summary> /// <typeparam name="T">Type of queryable objects.</typeparam> /// <param name="query">Query.</param> /// <param name="propertyName">Name of property.</param> /// <param name="method">Flag of order method.</param> /// <returns> /// Ordered queryable object (IOrderedQueryable). /// </returns> /// <remarks> /// Use reflection (not ComponentModel) to mirror LINQ. /// </remarks> private static IOrderedQueryable <T> Order <T>(IQueryable <T> query, string propertyName, EOrderMethod method) { Ensure.NotNull(query, nameof(query)); Ensure.NotEmpty(propertyName, nameof(propertyName)); string[] propertyNameParts = propertyName.Split('.'); Type type = typeof(T); ParameterExpression arg = Expression.Parameter(type, "x"); Expression expression = arg; foreach (string propertyNamePart in propertyNameParts) { PropertyInfo propertyInfo = type.GetProperty(propertyNamePart, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); if (propertyInfo == null) { throw new InvalidOperationException($"Nested property with name {propertyName} for type {typeof(T).Name} was not found."); } expression = Expression.Property(expression, propertyInfo); type = propertyInfo.PropertyType; } Type delegateType = typeof(Func <,>).MakeGenericType(typeof(T), type); LambdaExpression lambda = Expression.Lambda(delegateType, expression, arg); object result = typeof(Queryable).GetMethods().Single( m => m.Name == method.ToString() && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 2 && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(T), type) .Invoke(null, new object[] { query, lambda }); return((IOrderedQueryable <T>)result); }
private static IOrderedEnumerable <T> Order <T>(IEnumerable <T> source, string propertyName, EOrderMethod method) { Ensure.NotNull(source, nameof(source)); Ensure.NotEmpty(propertyName, nameof(propertyName)); string[] propertyNameParts = propertyName.Split('.'); Type type = typeof(T); ParameterExpression arg = Expression.Parameter(type, "x"); Expression expr = arg; foreach (string propertyNamePart in propertyNameParts) { // Use reflection (not ComponentModel) to mirror LINQ PropertyInfo propertyInfo = type.GetProperty(propertyNamePart); if (propertyInfo == null) { throw new InvalidOperationException($"Nested property with name {propertyName} for type {typeof(T).Name} was not found."); } expr = Expression.Property(expr, propertyInfo); type = propertyInfo.PropertyType; } Type delegateType = typeof(Func <,>).MakeGenericType(typeof(T), type); LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg); object result = typeof(Enumerable).GetMethods().Single( m => m.Name == method.ToString() && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 2 && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(T), type) .Invoke(null, new object[] { source, lambda.Compile() }); return((IOrderedEnumerable <T>)result); }