Dynamic Filtering
- by Ricardo Peres
Continuing my previous posts on dynamic LINQ, now it's time for dynamic filtering. For now, I'll focus on string matching. There are three standard operators for string matching, which both NHibernate, Entity Framework and LINQ to SQL recognize: Equals Contains StartsWith EndsWith So, if we want to apply filtering by one of these operators on a string property, we can use this code:
public enum MatchType
{
StartsWith = 0,
EndsWith = 1,
Contains = 2,
Equals = 3
}
public static List Filter(IEnumerable enumerable, String propertyName, String filter, MatchType matchType)
{
return (Filter(enumerable, typeof(T), propertyName, filter, matchType) as List);
}
public static IList Filter(IEnumerable enumerable, Type elementType, String propertyName, String filter, MatchType matchType)
{
MethodInfo asQueryableMethod = typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m = (m.Name == "AsQueryable") && (m.ContainsGenericParameters == false)).Single();
IQueryable query = (enumerable is IQueryable) ? (enumerable as IQueryable) : asQueryableMethod.Invoke(null, new Object [] { enumerable }) as IQueryable;
MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m = m.Name == "Where").ToArray() [ 0 ].MakeGenericMethod(elementType);
MethodInfo matchMethod = typeof(String).GetMethod
(
(matchType == MatchType.StartsWith) ?
"StartsWith" :
(matchType == MatchType.EndsWith) ?
"EndsWith" :
(matchType == MatchType.Contains) ?
"Contains" :
"Equals",
new Type [] { typeof(String) }
);
PropertyInfo displayProperty = elementType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
MemberExpression member = Expression.MakeMemberAccess(Expression.Parameter(elementType, "n"), displayProperty);
MethodCallExpression call = Expression.Call(member, matchMethod, Expression.Constant(filter));
LambdaExpression where = Expression.Lambda(call, member.Expression as ParameterExpression);
query = whereMethod.Invoke(null, new Object [] { query, where }) as IQueryable;
MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList", BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(elementType);
IList list = toListMethod.Invoke(null, new Object [] { query }) as IList;
return (list);
}
var list = new [] { new { A = "aa" }, new { A = "aabb" }, new { A = "ccaa" }, new { A = "ddaadd" } };
var contains = Filter(list, "A", "aa", MatchType.Contains);
var endsWith = Filter(list, "A", "aa", MatchType.EndsWith);
var startsWith = Filter(list, "A", "aa", MatchType.StartsWith);
var equals = Filter(list, "A", "aa", MatchType.Equals);
Perhaps I'll write some more posts on this subject in the near future.
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/2.0.320/scripts/clipboard.swf';
SyntaxHighlighter.brushes.CSharp.aliases = ['c#', 'c-sharp', 'csharp'];
SyntaxHighlighter.all();