Created
December 3, 2015 23:57
-
-
Save khalidabuhakmeh/14f4f2e10e777bbb35d2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 class SearchExtensions | |
{ | |
public static IQueryable<T> Search<T>(this IQueryable<T> value, object search) | |
{ | |
if (search == null) | |
{ | |
return value; | |
} | |
var filterProperties = search | |
.GetType() | |
.GetProperties(BindingFlags.Public | BindingFlags.Instance) | |
.Where(x => x.CanRead) | |
.Where(x => x.PropertyType == typeof(string) || (typeof(IEnumerable).IsAssignableFrom(x.PropertyType) && | |
x.PropertyType != typeof(string))); | |
var validValueProperties = typeof(T) | |
.GetProperties(BindingFlags.Public | BindingFlags.Instance) | |
.Where(x => x.CanRead) | |
.ToDictionary(x => x.Name, x => x, StringComparer.OrdinalIgnoreCase); | |
var type = typeof(T); | |
var stringType = typeof(string); | |
var parameter = Expression.Parameter(type, "x"); | |
var containsMethod = stringType.GetMethod("Contains", new[] { stringType }); | |
Expression orExpressions = null; | |
foreach (var property in filterProperties) | |
{ | |
PropertyInfo validValueProperty; | |
validValueProperties.TryGetValue(property.Name, out validValueProperty); | |
var filterPropertyValue = property.GetValue(search, null); | |
if (validValueProperty != null && filterPropertyValue != null) | |
{ | |
if (typeof (IEnumerable).IsAssignableFrom(property.PropertyType) && | |
property.PropertyType != typeof (string)) | |
{ | |
foreach (var arrayValue in (IEnumerable)filterPropertyValue) | |
{ | |
if (arrayValue == null || arrayValue.GetType() != typeof (string)) | |
continue; | |
orExpressions = OrExpressionBuilder<T>(arrayValue, parameter, validValueProperty, property, containsMethod, orExpressions); | |
} | |
} | |
else | |
{ | |
orExpressions = OrExpressionBuilder<T>(property.GetValue(search, null), parameter, validValueProperty, property, containsMethod, orExpressions); | |
} | |
} | |
} | |
if (orExpressions != null) | |
{ | |
var whereCallExpression = Expression.Call( | |
typeof (Queryable), | |
"Where", | |
new[] {value.ElementType}, | |
value.Expression, | |
Expression.Lambda<Func<T, bool>>(orExpressions, new[] {parameter})); | |
return value.Provider.CreateQuery<T>(whereCallExpression); | |
} | |
else | |
{ | |
return value; | |
} | |
} | |
private static Expression OrExpressionBuilder<T>(object value, ParameterExpression parameter, | |
PropertyInfo validValueProperty, PropertyInfo property, MethodInfo containsMethod, Expression orExpressions) | |
{ | |
var searchExpression = Expression.Property(parameter, validValueProperty); | |
var searchTermExpression = Expression.Constant(value); | |
var callContainsMethod = Expression.Call(searchExpression, containsMethod, searchTermExpression); | |
orExpressions = orExpressions == null | |
? (Expression) callContainsMethod | |
: Expression.Or(orExpressions, callContainsMethod); | |
return orExpressions; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment