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);