Taking the Magic out of Expression<T>

I have seen many people gawk at the use of Expression<T> in all sorts of ways, and to someone coming from a static language it may seem like pure magic (or witchcraft depending on your outlook!). In reality though, Expression<T> is really nothing to stand in awe of, and you too can start using it in very measured ways in your applications.

Let’s first start off by declaring a simple lambda and assigning it to a Func delegate.

Sidenote:

If you aren’t familiar with lambdas, then go check out the second post in my functional programming series.

Func<string, int> length = s => s.Length;

Now that we have defined our length delegate we can call it just like any delegate:

string myString = "some string";
int stringLenght = length(myString);

But we can wrap our “Func<string,int>” in an Expression<T> like this:

Expression<Func<string, int>> length = s => s.Length;

But now we can’t call it anymore. Why is that? Well, “length” is no longer a delegate, but instead it is an expression tree. An expression tree is simply a tree structure that represents the lambda “s => s.Length”. Instead of the C# compiler turning this into an executable method, it simply goes through the syntax and forms a tree that expresses what the lambda is doing.

In fact, there is a method on the Expression type called “Compile” that lets us turn this expression tree into a Func<string, int> that we can run:

Func<string,int> lengthMethod = length.Compile();
int stringLength = lengthMethod(myString);

Pretty cool stuff. But why would we want to get expression trees instead of a compiled delegate? Well, the answer is both simple and complex. We would want an expression tree because we might want to use the information about the lambda to do something different than what the compiled code might actually do. Whaaaaat? Yep, you read that right, we might want an expression because when we say “Where(t => t.StartsWith(“a”))” in a linq expression we don’t actually want to call the “StartsWith” method, intead we want to translate that into a “t LIKE ‘a%'” SQL statement. Got that?

If we can walk the tree that describes the lambda, then we can figure out what the lambda is trying to do and then perform some other task. For example, one of the things that I am currently doing at work is developing a way to have rules get tied to properties on a class and then in turn tie those back to validation displays that the user can see on the front end. One option would be to pass strings that represent the names of the properties, and another would be to generate enumerations that represent the properties on a class. The problem with these is that in the first one, if names of properties changed then you could potentially have issues where you forget to update an interface to the new string, and in the second we have to deal with giant enumerations and using those things all over the place. Plus we either have to create them manually or use some sort of Code-Gen to create them (yuck!).

But how do we solve this with expression trees? Well, let’s define a class like this:

public class Rule<T>
{
    public Rule<T> BindRuleTo<U>(Expression<Func<T,U>> expression)
    {
        //do something with the expression here
        return this;
    }
}

Here we are declaring a Rule class and we can now bind the rule to a property. I have yet to implement the actual work, but lets look at how we would call it first:

var rule = new Rule<User>();
rule.BindRuleTo(u => u.Username);

Here we have a Rule associated with a User class and then we bind the rule to the Username property on the user class. We get strong typing and full intellisense here because C# can infer that the type going into the lambda is a “User” type due to us declaring the Rule class as Rule<T>. Because C# knows the user class goes in, then once we specify a property it can also infer “U” because it knows the type coming out of the lambda as well! It makes our syntax much more clean without all of the angle brackets.

But how do we now turn this expression into something that we can use? All we have to do is inspect our expression. Since we are only allowing a property to be passed in (this isn’t constrained at compile time though, we have to check it at runtime) we can very easily limit the amount of parsing that we have to do. Since this is an expression tree, we know that the root is always going to be of type “LambdaExpression”, so we can just cast to that type. The “LambdaExpression” type has two properties, “Body” and “Parameters”. These hold the expressions for the body of the lambda and the parameters passed to the lambda. In this instance we know that the User class is being passed in, so we don’t really care about the parameters, so we are only going to work with the body.

public Rule<T> BindRuleTo<U>(Expression<Func<T,U>> expression)
{
    var lambda = (LambdaExpression)expression;
    
    if (lambda.Body.NodeType != ExpressionType.MemberAccess)
    {
        throw new InvalidOperationException("Expression must be a MemberExpression");
    }

    var memberExpression = (MemberExpression)lambda.Body;

    
    return this;
}

Here you can see that we are expecting the body of the lambda to be a “MemberExpression”. This is the type of expression that represents an access to a field or property on a class. In this case, the member expression would represent “u.Username”. This also has two properties on it, one called “Expression” and the other is called “Member”. The “Expression” property holds an Expression that represents the class on the left of the dot and the “Member” property holds a MemberInfo object that has info about the member on the right of the dot.

If you have dealt with reflection at any point, then you have probably seen MemberInfo objects all over the place before. In this case, since we are expecting a property then this MemberInfo object should actually be a PropertyInfo, so we can add a check for that:

public Rule<T> BindRuleTo<U>(Expression<Func<T,U>> expression)
{
    var lambda = (LambdaExpression)expression;
    
    if (lambda.Body.NodeType != ExpressionType.MemberAccess)
    {
        throw new InvalidOperationException("Expression must be a MemberExpression.");
    }

    var memberExpression = (MemberExpression)lambda.Body;
    
    var propertyInfo = memberExpression.Member as PropertyInfo;
    if (propertyInfo == null)
    {
        throw new InvalidOperationException("Expression must be a property reference.");
    }

    
    return this;
}

Now that we have our PropertyInfo object, all we have to do now is pull the data off of it that we need. In our case, all we really need is the name of the property to use to tie it to another place where we will pass in the same property.

Now you are going to obviously want to refactor this out into a library that you can use anywhere you need to. So most likely this method would look something like this:

public Rule<T> BindRuleTo<U>(Expression<Func<T,U>> expression)
{                
    this.PropertyName = ExpressionUtil.GetPropertyNameFromExpression(expression);                
    return this;
}

Now you can define a method somewhere else that looks up rules based on an expression that you pass in. And now you have intellisense everywhere, strong typing, and if a property name changes you’ll get compile time errors without lots of enumerations! If you want to extend this concept further, then you’ll just to do some research to find the expression types that represent the lamdas that you want to express. There is an expression tree visualizer that comes in the samples with visual studio that will allow you to look at your expression trees like this:

Expression Tree

This will make it much easier for you to discover what expressions you will need to accomplish your task! I hope you found this useful!

Be Sociable, Share!

7 comments

  1. Thanks — this is finally making sense.

  2. Justin,

    Nice article and good explanations. Thanks…

    Mike

  3. Justin,

    This is all syntatical candy but one change I’d recommend is to drop the helper class ExpressionUtil and turn that method into an extension method since you’re obviously using 3.5.

    Then your code would simply be

    public Rule<T> BindRuleTo<U> Expression<Func<T,U>> expression)
    {
    this.PropertyName = expression.GetPropertyName();
    return this;
    }

  4. Hi Justin,

    I’ve just began reading your "functional" series and "me like what there see" ;-)

    any book you’re planning to release? or any other series? very few programmers can "explain" or teach things how they really work and althought you aren’t the greatest I’ve ever read, you are definitely amongs the best ones heh =D

    this isn’t the book after all but the series of "short" articles so respect!

    I’ve just glimpsed on this one (I am still in lambda window ;-) and it is too fast for me right now, I’ll see if it will be alright when I finish your functional series and try to use lambdas everywhere =)

    thanks

  5. Excellent article!

  6. I have been searching for a while for an explanation like this.
    Thank you for the thorough article. Good work.

  7. Super nice article – Thanks for explanation how these Lambda expressions can be used – I started to use NHibernate and was stuck with all these Lambda expressions. Thanks to your article I got the idea behind this…

Leave a Reply

Your email address will not be published. Required fields are marked *