Expression Tree Based Activators


In the previous part, in the convention based factory, we used the Activator class CreateInstance() method to create a parser dynamically using a type infomation:

activator = 
  stream => Activator.CreateInstance(
              parserType,
              BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
              null,
              new object[] { stream },
              CultureInfo.CurrentCulture) as IEnumerator<Person>;

This solution works well in our example, but there is a faster way to create class instances than using Activator.

Lambda Expressions and Anonymous Methods

If we know the type of the class we want to create, it is simple to build activators:

public class XmlParser : IEnumerator<Person>
{
    public XmlParser(Stream stream) ...
}

public class BinParser : IEnumerator<Person>
{
    public BinParser(Stream stream) ...
}

...

Func<Stream, IEnumerator<Person>> activator_1 = s => new XmlParser(s);
Func<Stream, IEnumerator<Person>> activator_2 = s => new BinParser(s);

...

var parser = activator_1(stream);

Now we can pass around activator_1 or activator_2, the caller of the activator doesn’t need to know how and what specific type will be created.

In the example above the activator is implemented using a Lambda Expression. This expression will be transformed by the compiler into a method with a generated name. The result will be more or less the following – given that the program lines were written in a method called “Main”:

static IEnumerator<Person> <Main>b_0(Stream s)
{
    return new XmlParser(s);
}

...

Func<Stream, IEnumerator<Person>> activator_1 = 
  new Func<Stream, IEnumerator<Person>>(<Main>b_0);

...

var parser = activator_1(stream);

Now if we want to use lambda expressions in the ParserFactoryConfig to create activators like above, we will have a problem, because we do not know the concrete types in advance, so we do not know what to write after the ‘new’ keyword. The best would be if we could put types after the ‘new’ keyword runtime.

Expression Trees

Fortunately, this all is possible using Expression Trees. What is an Expression Tree? First, let’s notice that although I almost always use “var” for variable declaration, I didn’t do that for the activators. Would the following line compile?

var activator_1 = s => new XmlParser(s);

It would not, for a reason. The right side is a lambda expression, the compiler had to figure out the type of the variable on the left side from that. Why can’t it do this? Because lambda expressions don’t have a type. They can be converted to a compatible delegate type, like ‘Func<Stream, IEnumerator>’ or – and this is the interesting part for us – to an expression tree. It cannot decide which one we want, unless we tell it, specifying the type of the left side:

Func<Stream, IEnumerator<Person>> activator_1 = s => new XmlParser(s);

or

Expression<Func<Stream, IEnumerator<Person>>> activator_1 = s => new XmlParser(s);

We have already seen how the first version will be compiled. That will result an ordinary method with a slightly strange name like b_0. The second version is much more interesting. That will be an IL code which does something like the following:

ParameterExpression parameter = Expression.Parameter(typeof(Stream), "s");
ConstructorInfo construtorInfo = typeof(XmlParser).GetConstructor(...)
 
Expression<Func<Stream, IEnumerator<Person>>> activator_1 = 
    Expression.Lambda<Func<Stream, IEnumerator<Person>>>(
        Expression.New(
            construtorInfo , 
            new Expression[] { parameter }), 
        new ParameterExpression[] { parameter  });

What do we see? The compiler generated a code, which builds a data structure based on the Expression class. This data structure represents the lambda expression we wrote in C#. Because we wrote a lambda expression, the outmost call is an Expression.Lambda(). Our original lamda expression has a parameter and a body. The parameter became the second argument of the Expression.Lambda() call, and the body is the first argument. The body is created with the Expression.New() call, which gets the type information by a ConstructorInfo class, and the parameter for the constructor. A complex case would embed more calls into each other, and if we drew the diagram of the call sequence, it would result a tree like structure, hence the name of the expression tree. Our simple case is not really a tree, but the data structure created by the calls above looks a bit similar:

ExprTree

Benefits of Expression Trees

We can win two things using Expression Trees. First, we can dynamically put them together, using any ConstructorInfo with Expression.New(). Second, Expression Trees can be compiled runtime, and the compiled code will be really fast. We can write the following to get the compiled version of the activator:

Func<Stream, IEnumerator<Person>> activatorAsDelegate = 
  activator_1.Compile() as Func<Stream, IEnumerator<Person>>;

Now it can be used to create a parser:

var parser = activatorAsDelegate(stream);

Using this trick, we can make our Factory faster, if we modify the activator creation in the ParserFactoryConfig class TryCreateActivator method.

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: