Dynamic Filtering

Posted by Ricardo Peres on ASP.net Weblogs See other posts from ASP.net Weblogs or by Ricardo Peres
Published on Sat, 10 Apr 2010 17:16:30 GMT Indexed on 2010/04/10 17:23 UTC
Read the original article Hit count: 405

Filed under:
|
|

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.

Bookmark and Share

© ASP.net Weblogs or respective owner

Related posts about .NET

Related posts about LINQ