Created
January 24, 2019 10:54
-
-
Save sgissinger/1d2e40ce7e3fda60019853b5795a7487 to your computer and use it in GitHub Desktop.
DynamicLinq
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static IQueryable<T> OrderBy<T>(this IEnumerable<T> source, IEnumerable<ISortable> sortables, IEnumerable<string> persistentColumnNames) | |
{ | |
return source.AsQueryable().OrderBy(sortables, persistentColumnNames); | |
} | |
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, IEnumerable<ISortable> sortables, IEnumerable<string> persistentColumnNames) | |
{ | |
if (source == null) | |
throw new ArgumentNullException("source"); | |
if (sortables == null) | |
throw new ArgumentNullException("orders"); | |
var type = typeof(T); | |
var first = true; | |
foreach (var sortable in sortables) | |
{ | |
if (persistentColumnNames.Contains(sortable.ColumnName)) | |
continue; | |
var command = first ? "OrderBy" : "ThenBy"; | |
if (sortable.IsDescending) | |
command = string.Format("{0}Descending", command); | |
var property = type.GetProperty(sortable.ColumnName); | |
var parameter = Expression.Parameter(type, "p"); | |
var propertyAccess = Expression.MakeMemberAccess(parameter, property); | |
var lambdaExpression = Expression.Lambda(propertyAccess, parameter); | |
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, | |
source.Expression, Expression.Quote(lambdaExpression)); | |
source = source.Provider.CreateQuery<T>(resultExpression); | |
first = false; | |
} | |
return source; | |
} | |
public static IQueryable<T> Where<T>(this IEnumerable<T> source, IEnumerable<IFilterable> filterables, IEnumerable<string> persistentColumnNames) | |
{ | |
return source.AsQueryable().Where(filterables, persistentColumnNames); | |
} | |
public static IQueryable<T> Where<T>(this IQueryable<T> source, IEnumerable<IFilterable> filterables, IEnumerable<string> persistentColumnNames) | |
{ | |
if (source == null) | |
throw new ArgumentNullException("source"); | |
if (filterables == null) | |
throw new ArgumentNullException("filters"); | |
var type = typeof(T); | |
foreach (var filterable in filterables) | |
{ | |
if (persistentColumnNames.Contains(filterable.ColumnName)) | |
continue; | |
var property = type.GetProperty(filterable.ColumnName); | |
// TODO: Extend in order to manage other cases, this one only take care of string equalities | |
if (property.PropertyType == typeof(string)) | |
{ | |
var parameter = Expression.Parameter(type, "p"); | |
var propertyAccess = Expression.MakeMemberAccess(parameter, property); | |
var value = Expression.Constant(filterable.Value); | |
var expression = Expression.Equal(value, value); | |
if (filterable.Operator == "eq") | |
expression = Expression.Equal(propertyAccess, value); | |
else if (filterable.Operator == "like") | |
expression = LikeOrNotLike(propertyAccess, value, true); | |
else if (filterable.Operator == "notLike") | |
expression = LikeOrNotLike(propertyAccess, value, false); | |
var lambdaExpression = Expression.Lambda(expression, parameter); | |
var resultExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { type }, | |
source.Expression, lambdaExpression); | |
source = source.Provider.CreateQuery<T>(resultExpression); | |
} | |
} | |
return source; | |
} | |
private static BinaryExpression LikeOrNotLike(MemberExpression propertyAccess, ConstantExpression value, bool like) | |
{ | |
var cmp = Expression.Constant(StringComparison.InvariantCulture); | |
var indexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) }); | |
var toLower = typeof(string).GetMethod("ToLower", Type.EmptyTypes); | |
var valueToLower = Expression.Call(value, toLower); | |
var propertyToLower = Expression.Call(propertyAccess, toLower); | |
var left = Expression.Call(propertyToLower, indexOf, valueToLower, cmp); | |
BinaryExpression expression; | |
if (like) | |
{ | |
var right = Expression.Constant(0, typeof(int)); | |
expression = Expression.GreaterThanOrEqual(left, right); | |
} | |
else | |
{ | |
var right = Expression.Constant(-1, typeof(int)); | |
expression = Expression.Equal(left, right); | |
} | |
return expression; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment