Skip to content

Instantly share code, notes, and snippets.

@sgissinger
Created January 24, 2019 10:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sgissinger/1d2e40ce7e3fda60019853b5795a7487 to your computer and use it in GitHub Desktop.
Save sgissinger/1d2e40ce7e3fda60019853b5795a7487 to your computer and use it in GitHub Desktop.
DynamicLinq
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