Dynamic LINQ Methods
Continuing the Dynamic LINQ series, here are some hopefuly useful methods for performing LINQ queries in IQueryable or IQueryable<T> object, with String parameters. The available methods, so far, are:
- GroupBy
- OrderBy
- Skip
- Take
- WhereEquals
- WhereNotEquals
public static class QueryableExtensions { public static IQueryable<T&> WhereNotEquals<T&>(this IQueryable<T&> query, String propertyName, Object value) { return (WhereNotEquals(query as IQueryable, propertyName, value) as IQueryable<T&>); } public static IQueryable WhereNotEquals(this IQueryable query, String propertyName, Object value) { Type propertyType = query.GetType().GetGenericArguments() [ 0 ]; MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "Where").ToArray() [ 0 ].MakeGenericMethod(propertyType); ParameterExpression parameter = Expression.Parameter ( propertyType, "m" ); MemberExpression member = Expression.MakeMemberAccess ( parameter, propertyType.GetProperty(propertyName) ); BinaryExpression equal = ParameterExpression.NotEqual ( member, (value != null) ? Expression.Constant(value, value.GetType()) : null ); LambdaExpression lambda = Expression.Lambda ( typeof(Func<,>).MakeGenericType(propertyType, typeof(Boolean)), equal, member.Expression as ParameterExpression ); query = whereMethod.Invoke(null, new Object [] { query, lambda }) as IQueryable; return (query); } public static IQueryable<T&> WhereEquals<T&>(this IQueryable<T&> query, String propertyName, Object value) { return (WhereEquals(query as IQueryable, propertyName, value) as IQueryable<T&>); } public static IQueryable WhereEquals(this IQueryable query, String propertyName, Object value) { Type propertyType = query.GetType().GetGenericArguments() [ 0 ]; MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "Where").ToArray() [ 0 ].MakeGenericMethod(propertyType); ParameterExpression parameter = Expression.Parameter ( propertyType, "m" ); MemberExpression member = Expression.MakeMemberAccess ( parameter, propertyType.GetProperty(propertyName) ); BinaryExpression equal = ParameterExpression.Equal ( member, (value != null) ? Expression.Constant(value, value.GetType()) : null ); LambdaExpression lambda = Expression.Lambda(typeof(Func<,>).MakeGenericType(propertyType, typeof(Boolean)), equal, member.Expression as ParameterExpression); query = whereMethod.Invoke(null, new Object[]{ query, lambda }) as IQueryable; return(query); } public static IQueryable<T&> GroupBy<T&>(this IQueryable<T&> query, String propertyName) { return (GroupBy(query as IQueryable, propertyName) as IQueryable<T&>); } public static IQueryable GroupBy(this IQueryable query, String propertyName) { Type propertyType = query.GetType().GetGenericArguments() [ 0 ]; PropertyInfo property = propertyType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public); MethodInfo groupByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "GroupBy" && m.GetParameters().Length == 2).ToArray() [ 0 ].MakeGenericMethod(propertyType, property.PropertyType); ParameterExpression parameter = Expression.Parameter ( propertyType, "m" ); MemberExpression member = Expression.MakeMemberAccess ( parameter, propertyType.GetProperty(propertyName) ); LambdaExpression lambda = Expression.Lambda ( typeof(Func<,>).MakeGenericType(propertyType, property.PropertyType), member, member.Expression as ParameterExpression ); query = groupByMethod.Invoke(null, new Object [] { query, lambda }) as IQueryable; return (query); } public static IQueryable<T&> OrderBy<T&>(this IQueryable<T&> query, params String [] properties) { return (OrderBy(query as IQueryable, properties) as IQueryable<T&>); } public static IQueryable OrderBy(this IQueryable query, params String [] properties) { properties = (properties == null) ? new String [ 0 ] : properties.Distinct().ToArray(); Type propertyType = query.GetType().GetGenericArguments()[ 0 ]; MethodInfo orderByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "OrderBy").ToArray() [ 0 ]; MethodInfo orderByDescMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "OrderByDescending").ToArray() [ 0 ]; MethodInfo orderThenByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "ThenBy").ToArray() [ 0 ]; MethodInfo orderThenByDescMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "ThenByDescending").ToArray() [ 0 ]; String [] parts = null; MethodInfo method = null; PropertyInfo property = null; MemberExpression member = null; LambdaExpression orderBy = null; for (Int32 i = 0; i < properties.Length; ++i) { parts = properties[ i ].Split(' '); property = propertyType.GetProperty(parts[ 0 ], BindingFlags.Instance | BindingFlags.Public); if ((parts.Length == 1) || (parts [ 1 ].Equals("asc", StringComparison.OrdinalIgnoreCase) == true)) { if (i == 0) { method = orderByMethod.MakeGenericMethod(propertyType, property.PropertyType); } else { method = orderThenByMethod.MakeGenericMethod(propertyType, property.PropertyType); } } else if (parts[ 1 ].Equals("desc", StringComparison.OrdinalIgnoreCase) == true) { if (i == 0) { method = orderByDescMethod.MakeGenericMethod(propertyType, property.PropertyType); } else { method = orderThenByDescMethod.MakeGenericMethod(propertyType, property.PropertyType); } } member = Expression.MakeMemberAccess ( Expression.Parameter(propertyType, "n"), property ); orderBy = Expression.Lambda ( member, member.Expression as ParameterExpression ); query = method.Invoke(null, new Object [] { query, orderBy }) as IQueryable; } return (query); } public static IQueryable Take(this IQueryable query, Int32 pageSize) { Type propertyType = query.GetType().GetGenericArguments() [ 0 ]; MethodInfo takeMethod = typeof(Queryable).GetMethod("Take", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(propertyType); query = takeMethod.Invoke(null, new Object [] { query, pageSize }) as IQueryable; return (query); } public static IQueryable Skip(this IQueryable query, Int32 pageIndex) { Type propertyType = query.GetType().GetGenericArguments() [ 0 ]; MethodInfo skipMethod = typeof(Queryable).GetMethod("Skip", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(propertyType); query = skipMethod.Invoke(null, new Object [] { query, pageIndex }) as IQueryable; return (query); } }
Here are some examples:
IQueryable q = ...; q = q.OrderBy("NAME asc", "BIRTHDAY desc"); q = q.WhereEquals("NAME", "bla"); q = q.GroupBy("PROFILE"); q = q.Take(10);