# Monday, August 09, 2010
« Tip of the Day: An extension method to H... | Main | Tip of the Day: Creating a control that ... »
I designed a control to filter data dynamically, and I wanted to be able to be able to use it to filter either SQL Data (via a DataTable) or a List<T> of objects. Sorting the DataTable dynamically is easy using the DataTable, as you can create a DataView and perform case insensitive searches like this:

DataView dvData = new DataView(data);
dvData.RowFilter = “SomeField=’Test’”;
You can also create widcard searches like this:
DataView dvData = new DataView(data);
dvData.RowFilter = “SomeField LIKE ’Te%’”;
But providing that functionality with List<T> and LINQ was going to be a challenge.  If you know the properties you want to find in advance, the syntax is easy using Lambda functions:
List<MyObject> objectResults = MyList.FindAdd(x  => x.MyProperty.ToLower() == “Value”);
That’s well and good, but in my filter control, I wanted to be able to specify a property by name for a comparison.  Something like this:
List<MyObject> objectResults = MyList.FindAdd(x  => “MyPropertyName” == “Value”);
Unfortunately, that’s not going to work. I needed something that would dynamically specify the property I want to search. In a previous post I described how I could use a defined Lambda Expression to dynamically sort a list in a similar fashion.

So in my first attempt and doing a lot of searching on Google, I came up with this method:

    public static IEnumerable<T> DynamicFilter<T>(this IEnumerable<T> source, string propertyOrFieldName, string searchValue)
    {
        Func<T, bool> predicate = CreatePredicate<T>(propertyOrFieldName, searchValue);

        return source.Where(predicate);
    }

    static Func<T, bool> CreatePredicate<T>(string propertyOrFieldName, string searchValue)
    {
        var arg = Expression.Parameter(typeof(T), "arg");
        var body = Expression.Equal(Expression.Property(arg, propertyOrFieldName), Expression.Constant(searchValue));

        return Expression.Lambda<Func<T, bool>>(body, arg).Compile();
    }
Usage: 
List<Employee> emps = Employee.LoadListCollection();
List<Employee> empList = emps.DynamicFilter("FirstName", "Angie").ToList();
This worked great for a case-sensitive search, but I still didn’t have a way to do a case-insensitve search or a wildcard search. So after some more searching and more trial-and-error, I came up with this for a wildcard search:
public static IEnumerable<T> ContainsString<T>(this IEnumerable<T> data, string propertyOrFieldName, string searchValue)
    {
        var param = Expression.Parameter(typeof(T), "x");
        var body = Expression.Call(
            typeof(BusinessObjectBase).GetMethod("Like",
                BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public),
                Expression.PropertyOrField(param, propertyOrFieldName),
                Expression.Constant(searchValue, typeof(string)));
        var lambda = Expression.Lambda<Func<T, bool>>(body, param);
        return data.Where(lambda.Compile());
    }
A couple things to note here. First, I needed  to add a method “Like” to my base object (BusinessObjectBase in this case) of the collections I am searching. It looks like this:
/// <summary>
    /// comparison operator. Needed for dynamically filtering the objects
    /// </summary>
    /// <param name="a">A.</param>
    /// <param name="b">The b.</param>
    /// <returns></returns>
    static bool Like(string a, string b)
    {
        return a.ToLower().Contains(b.ToLower());
    }
Now I can do a search where I specify the property name, and it returns and value of that property that contains any part of that string (and it is also case-insensitive).

List<Employee> emps = Employee.LoadListCollection();
List<Employee> empList = emps.ContainsString("FirstName", "An").ToList();
Then it occurred to me that I was specifying the name of the static routine in the call. What would happen if I specified the name of the operator dynamically? Would it work right?
var body = Expression.Call(
            typeof(BusinessObjectBase).GetMethod("Like",
                BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public),

Became this:

var body = Expression.Call(
            typeof(BusinessObjectBase).GetMethod(operatorName,
                BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public),
Now I could create two static operators (or as many as I might ever need) to provide this dynamic functionality.

public static IEnumerable<T> RunOperator<T>(this IEnumerable<T> data, string operatorName, string propertyOrFieldName, string searchValue)
    {
        var param = Expression.Parameter(typeof(T), "x");
        var body = Expression.Call(
            typeof(BusinessObjectBase).GetMethod(operatorName,
                BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public),
                Expression.PropertyOrField(param, propertyOrFieldName),
                Expression.Constant(searchValue, typeof(string)));
        var lambda = Expression.Lambda<Func<T, bool>>(body, param);
        return data.Where(lambda.Compile());
    }
In my BusinessObjectBase class, I added the following methods (Like for wildcard searches, and Equals for a case-insensitive search):
    static bool Like(string a, string b)
    {
        return a.ToLower().Contains(b.ToLower());
    }
    static bool Equals(string a, string b)
    {
        return a.ToLower() == b.ToLower();
    }
I can call both of these methods like this:
public List<T> FilterData<T>(List<T> data, bool wildcardSearch)
{
List<T> results = data;
if (wildcardSearch)
          results = results.RunOperator("Like", fi.DataField, fi.FilterValue()).ToList();
       else
     results = results.RunOperator("Equals", fi.DataField, fi.FilterValue()).ToList();
    return results;
}
So let’s break it down a little. First, the first parameter of a lambda expression, which is what we are building here, is the input parameter, or in this case, the x portion of x =>.
var param = Expression.Parameter(typeof(T), "x");
Next, we’re setting up the call which is made to the right of the => of the Lambda expression. The code below is saying “grab the method name provided by the operatorName variable, which can be found in any class which implements the BusinessObjectBase class.

typeof(BusinessObjectBase).GetMethod(operatorName,

The result of the expression defined above will be returning a boolean, as defined here:
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
Finally, we return the data which evaluates in the lambda expression as true via this line of code:

return data.Where(lambda.Compile());
Note the delegate lambda expression is compiled into executrable code and produces a delegate which represents the lambda expression.
Obviously, understanding how to dynamically call methods and compare properties using LINQ is extremely powerful and has many,many possibilities. I hope this helps someone else trying to do the same thing!

Comments are closed.