Traversing Expression Trees

The Expression<T> data type which was introduced together with LINQ is interesting. When a Func<TResult> is wrapped in an Expression<T> the code is no longer completely compiled, instead it is preserved as an expression tree that can be traversed during runtime. This is what the method ExpressionHelper.GetExpressionText() that I used in my last post Type Safe SelectList Factory utilizes. In that post I used a simple lambda to select a property of a class.

IEnumerable = GetPeople();
SelectList selectList = 
  people.ToSelectList(people, p => p.Id, p => p.FullName);

To check how this works under the hood, I inspected the lambda object in a debugger and made a graph overview with the excellent dot tool.

The expression has been parsed into an object tree, but it still contains exactly the same information. Looking at the figure above we can see that it reflects the p => p.FullName lambda.

Before finding out that ExpressionHelper.GetExpressionText() exists, I wrote my own version, which I will show here as an example of using expression trees. It is adopted from a blog post I found when I had a similar problem with an ObjectDataSource.

private static string ExtractFieldName(
  Expression> expression)
  // Make sure that we have a lambda expression in the right format
  var lambda = (LambdaExpression)expression;
  if(lambda.Body.NodeType != ExpressionType.MemberAccess)
    throw new InvalidOperationException(
      "Expression must be a MemberAccess expression.");
  var memberAccess = (MemberExpression)lambda.Body;
  return memberAccess.Member.Name;

The function analyzes the parse tree of the lambda expression and extracts the name of the member. The name is in a property two levels down in the object hierarchy, and there is some casting and error checking required first, but then it is just a simple return of the found string. This is quite a simple example, with no alternative constructions. With more advanced expression trees things will quickly become much more complex. Still I think that it is a really cool technology in the .NET toolbox that is worth the complexity in some cases.

Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.