Pages

Saturday, June 2, 2012

Dynamic Filtering With LINQ

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


No comments:

Post a Comment