Tuesday, August 26, 2008 12:59 AM bart

To Bind or Not To Bind – Dynamic Expression Trees – Part 0

By now, most of my blog readers will be familiar with the simple concept of expression trees in C# 3.0 and VB 9.0. A quick recap. What’s the type of the expression below?

(string s, int a, int b) => s.Substring(a, b)

Shockingly, you can’t tell. Why? Lambdas have two forms of representation: code (as anonymous methods) or data (as expression trees). One more time:

Func<string, int, int, string> code = (string s, int a, int b) => s.Substring(a, b);

produces

Func<string, int, int, string> code = delegate (string s, int a, int b) { return s.Substring(a, b); };

where

Expression<Func<string, int, int, string>> data = (string s, int a, int b) => s.Substring(a, b);

produces (deep breadth)

ParameterExpression s = Expression.Parameter(typeof(string), “s”);
ParameterExpression a = Expression.Parameter(typeof(int), “a”);
ParameterExpression b = Expression.Parameter(typeof(int), “b”);

Expression<Func<string, int, int, string>> data = Expression.Lambda<Func<string, int, int, string>>(
    Expression.Call(s, typeof(string).GetMethod(“Substring”, new Type[] { typeof(int), typeof(int) }), a, b),
    s, a, b
);

When calling the Compile method on the produced (lambda-expression) data object we’ll get exactly the same IL code but generated at runtime through the form of a (delegate pointing at a) dynamic(ally generated) method using Reflection.Emit. So far, so good. But what are the characteristics of the expression tree’s generated code? Two things:

  • statically typed
  • early-bound

In more human terms, we know at compile time the type of all the involved expressions – at the entry points (i.e. the leaf levels) we’re passing it in with uttermost detail (see the Parameter factory method’s first argument for instance) but all intermediate nodes in the expression tree have a type too. E.g. the Expression.Call factory call returns a MethodCallExpression whose wrapped method call’s return type is System.String, hence that becomes the type of the node. Talking about method calls, those are bound at compile time too: we know precisely what method to call because of all the type information available about the arguments.

Isn’t this cool? Sure it is, but what about dynamic languages? Are those able to use this particular form of expression trees? The simple answer is no; well, at least not in a dynamic way, meaning with dynamic typing (i.e. the type of every node is determined at run time) and late binding for methods (i.e. we hope to find a suitable method overload at runtime). What can we do about this? Here we’re getting in the realm of DLR stuff and such. This blog series is not about DLR itself though, it’s rather about outlining some crucial concepts of dynamic typing including “dynamic expression trees” emitting dynamic call sites using binders.

In the first part coming up soon, we’ll start by investigating how to build dynamic expression trees.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Comments

# Dew Drop - August 26, 2008 | Alvin Ashcraft's Morning Dew

Tuesday, August 26, 2008 5:31 AM by Dew Drop - August 26, 2008 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop - August 26, 2008 | Alvin Ashcraft's Morning Dew

# Reflective Perspective - Chris Alcock &raquo; The Morning Brew #166

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #166

# WMOC#17 - PhotoSynth, Reflector move forward - Service Endpoint

Pingback from  WMOC#17 - PhotoSynth, Reflector move forward - Service Endpoint

# Afternoon Coffee 174 &#8211; DevHawk

Sunday, April 17, 2011 7:30 AM by Afternoon Coffee 174 – DevHawk

Pingback from  Afternoon Coffee 174 &#8211; DevHawk

# Dynamic LINQ and Dynamic Lambda expressions? - Programmers Goodies

Pingback from  Dynamic LINQ and Dynamic Lambda expressions? - Programmers Goodies