Composing Statements with Expression Trees in .NET 3.0

I was preparing some examples for my upcoming ALT.NET Workshop and thought that this might be of some interest to a few people.

Expression Trees’ primary raison d’être was to facilitate LINQ-y type stuff in the IQueryable implementations to support delayed execution and some other fun stuff.   Expression Trees, however, go much father than that. They are essentially a window in to the middle of the compilation process in .NET.  Imagine if you could hit PAUSE on the C# or VB compiler in mid-compile and take a snapshot of its internal state/model of the code before it does the final step of writing out the MSIL.  What if you could not only capture it, but you could manipulate and add to it before finishing the compilation and executing it? That’s exactly what Expression Trees are for (well, it doesn’t work EXACTLY like that, but it’s pretty close, close enough for this blog post anyhow).

We use Expression Trees a lot at Dovetail, in StructureMap, Fluent NHibernate, and various other projects primarily as a trick for fast reflection (static reflection).  But you can also compose whole new functionality with them to do some pretty crazy things. I don’t believe you could craft whole, complex programs via Expression Tree manipulation, but I would be delighted to be proven wrong in this statement.

Composing Simple Programs with Expression Trees

In this heavily contrived, overly simplistic example, I have these requirements:

  • Grab the value of a property P off an object A
  • Pass that value of A.P as an argument to a method B
  • Call method B

Assume that you don’t know, at compile time, that I don’t know what A, P, or B are. 

Let A be an instance of a class object.

Let B be a void method that takes one argument, of type System.Object ( i.e. void B(object));

NOTE: There are probably easier ways of doing this particular example, so don’t go off and start getting crazy with Expression Trees. It’s my hope that someone may find this useful in a much more complex example for which there is no easier alternative.

Ok, ok, enough disclaimer, so me the code!  First, a simple test which shows what we want to happen:  Take the OrderID from the order and print it to the console.

   1: [Test]
   2: public void hide_the_expression_tree_guts_in_another_method_below()
   3: {
   4:     var order = new Order {OrderID = "FUN!"};
   6:     Get_prop_value_and_execute_method(
   7:         order,
   8:         o => o.OrderID,
   9:         x => Console.WriteLine(x)
  10:     );
  11: }


Now, for the guts of Get_prop_value_and_execute_method:

   2: public void Get_prop_value_and_execute_method<A>(
   3:     A target,
   4:     Expression<Func<A, object>> propertyExpression,
   5:     Expression<Action<object>> methodExpression)
   6: {
   8:     // Define the parameters for the various lambda expression
   9:     // i.e. the 'x' in (x => x.Foo)
  10:     var parameters = propertyExpression.Parameters;
  12:     // Create an 'Invoke' expression to actually execute the property P getter
  13:     var getPropValueExpression = Expression.Invoke(
  14:                                         propertyExpression,
  15:                                         parameters.Cast<Expression>());
  17:     // Create a 'Call' expression to call the function with the value of property P
  18:     var methodBody = methodExpression.Body as MethodCallExpression;
  19:     var methodCall = Expression.Call(methodBody.Method, getPropValueExpression);
  21:     // Wrap it in a lambda so we can actually call it at runtime
  22:     var finalCall = Expression.Lambda<Action<A>>(methodCall, parameters);
  24:     // Compile the lambda to get an actual Action<A>
  25:     var action = finalCall.Compile();
  27:     // Execute it!
  28:     action(target);
  29: }

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in .NET, Expression Trees. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Mo

    Whoa! Thank you Mr. Chad! Keep it coming…