Archive for the ‘Expressions’ Tag

Dynamic Linq Queries

Alright, let’s assume that we are lazy coders, we have building a lot of Linq queries lately, and it’s getting repetitive. We keep having to remember to add a certain where clause to every query, couldn’t we just abstract this somehow? Well sure, we can use Expressions!

Let’s first take a look at the System.Linq.Queryable.Where extension method, here is the method’s signature:

public static IQueryable<TSource> Where<TSource>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, bool>> predicate);

Notice that it takes a lambda expression, which we can generate dynamically. For examples sake, let’s make a Foo and a Bar class, and two methods that generate a list of each:

static IEnumerable<Foo> MakeFoos()
{
    for (int i = 0; i < 10; i++)
        yield return new Foo { A = "Foo " + i, B = i };
}

static IEnumerable<Bar> MakeBars()
{
    for (int i = 0; i < 10; i++)
        yield return new Bar { A = "Bar " + i, B = i };
}

class Foo
{
    public string A { get; set; }
    public int B { get; set; }
}

class Bar
{
    public string A { get; set; }
    public int B { get; set; }
}

So what if we want to get all of the items in a collection with a and even B? What we need is an extension method that applies our filter to an IQueryable<> of any type. First off, let’s look at the method signature:

public static IQueryable<T> FilterB<T>(this IQueryable<T> query)

It’s fairly simple, it is an extension method that takes an IQueryable<T> and returns an IQueryable<T> so that we can keep our fluent interface going. The first thing we have to do in our method is create a parameter and property expression,

var param = Expression.Parameter(typeof(T), "x");
var prop = Expression.Property(param, "B");

Then we need a binary expression that %’s our property by 2,

var two = Expression.Constant(2);
var mod = Expression.MakeBinary(ExpressionType.Modulo, prop, two);

The ConstantExpressions are pretty self explanatory, they just hold the value that they are given. BinaryExpressions can represent any kind of binary expression, which is any expression that has a left and right side, like a == b, a != b, a + b, and b – a for example. Next, we need to make another binary expression that checks to see if our first binary expression, mod, is equal to zero:

var zero = Expression.Constant(0) ;
var eqZero = Expression.MakeBinary(ExpressionType.Equal, mod, zero);

Notice that we used one binary expression as a parameter for another, MakeBinary’s second and third parameters are just Expressions which can be any type of expression. All that is left to do is create the lambda expression, where it and return it:

var lambda = Expression.Lambda<Func<T, bool>>(eqZero, param);
return query.Where(lambda);

We don’t have to compile the lambda here because query providers use it in its raw expression tree form which they translate into whatever they need to get the job done. Here is the entire method:

public static IQueryable<T> FilterB<T>(this IQueryable<T> query)
{
    var param = Expression.Parameter(typeof(T), "x");
    var prop = Expression.Property(param, "B");

    var two = Expression.Constant(2);
    var mod = Expression.MakeBinary(ExpressionType.Modulo, prop, two);

    var zero = Expression.Constant(0);
    var eqZero = Expression.MakeBinary(ExpressionType.Equal, mod, zero);

    var lambda = Expression.Lambda<Func<T, bool>>(eqZero, param);
    return query.Where(lambda);
}

This should work with any query provider including Linq to SQL and the Entity Framework. We haven’t built in any error checking so expect it to throw if you use it on a collection of a type that does not have a B property. So, given the types we defined above, let’s see how we would use it:

var foos = MakeFoos().AsQueryable();
var bars = MakeBars().AsQueryable();

foreach (var foo in foos.FilterB())
    Console.WriteLine(foo.A);

foreach (var bar in bars.FilterB())
    Console.WriteLine(bar.A);

We are first getting collections of both Foos and Bars, and then changing them into IQueryable collections. we then just iterate over each collection after calling FilterB() on them. We could chain other calls after the FilterB call if we wanted. The output will be:

Foo 0

Foo 2

Foo 4

Foo 6

Foo 8

Bar 0

Bar 2

Bar 4

Bar 6

Bar 8

Yay! It works!

Using Expressions for Fun and Profit

Well, by now we all  know how to abuse System.Reflection to the point of absurdity, so now it’s time to start the abuse of System.Expressions. The System.Expressions namespace contains everything you need to build lambda expressions on the fly, then compile them at run time for use. One may ask “Why Bother?”, well my friend, the answer is Speed. If you are using reflection heavily in your projects, you are likely to get a nice speed boost by switching to Expressions. There are is one detail to keep in mind though, that the actual compilation of expressions can take some time, so you will want to cache the result.

First off, let’s take a look at a simple lambda, and then try to build it dynamically. Say we want to grab the length of a string:

Func<string, int> getStrLen = x => x.Length;

The lambda expression that we are assigning to the delegate has 2 main parts, the x parameter, and the x.Length property access. Let’s go ahead and create these two smaller expressions. Expressions use a factory pattern and can only be instantiated through static methods of off Expression so here is the code to build those two parts:

var param = Expression.Parameter(typeof(string), "x");
var prop = Expression.Property(param, "Length");

Expression.Parameter take a Type as the first parameter, which is the type of the parameter, and a string as the second parameter which is only used when you .ToString() the expression. Expression.Property takes another Expression as the first parameter, in our case we are using the ParameterExpression we created on the line before, but it can be a few other things like other PropertyExpressions, ConstantExpressions, CallExpressions, etc. The second parameter of Expression.Property is a string, it is just the name of the property you want to get. All that is left to do now is to build the lambda expression itself, and compile it:

var lambda = Expression.Lambda<Func<string, int>>(prop, param);
Func<string, int> result = lambda.Compile();

Expression.Lambda has both regular and generic versions, we want to use the generic because we want to be able to call it as directly as possible. The first parameter it takes is the body of the lambda, and in our case that is x.Length, which is our prop variable. Every parameter after the first should be ParameterExpressions representing parameters that you are passing to the lambda, and should match the order and number of the generic parameters on the delegate type that is used as the generic for Expression.Lambda. The call to lambda.Compile() is where the real magic happens, the library compiles our expression tree down to executable code. So, we’ve dynamically built the same lambda as we have assigned to getStrLen. if you are looking for more proof, check lambda.ToString(), which also comes in handy when you are trying to debug your expression building code. Alright, now let’s build a nice generic method using the same pieces as above, starting off with the method signature:

Func<T,R> BuildGetProperty<T, R>(string propName)

Our method will have two generic parameters, T which is the type containing the property, and R which is the type of the property, and one string that will be the name of the property to get. The body of our method is going to be almost verbatim of what is outlined above, except that we are going to substitute our generic types and property name. The end result is:

public static Func<T,R> BuildGetProperty<T, R>(string propName)
{
    var param = Expression.Parameter(typeof(T), "x");
    var prop = Expression.Property(param, propName);

    var lambda = Expression.Lambda<Func<T, R>>(prop, param);
    return lambda.Compile();
}

So, we could replace our getStrLen lambda above with:

var getStrLen = BuildGetProperty<string, int>("Length");

And to use it:

var len = getStrLen("woot");

Which would yield 4 as the result. I’ll be covering more on Expressions in further posts, so stay tuned. Also, comments are more than welcome since this is my first post.