Working with Expression Trees – Part 1

So here I am at 1.00 am in the morning everyone is sleeping and finally I can enjoy some peace and quite. My brain is partially not working so I apologize if I say something stupid 🙂

Let us start…. Why is LINQ so exciting for me? That’s a good question … Well 99% of the people that know me would probably answer “It is a new .Net feature so definitely Marlon will be more than excited about it!”. Yet my friends, let me give you the answer myself! The BIG thing about LINQ is that in C# you can stop being so imperative and bossy and start being more declarative (aka goal oriented). So basically you express yourself by creating a query and then let the underlying provider to do all the work…. To understand more what I mean have a look at Linq to SQL.

So assuming that you have already seen and tried LINQ, today I will talk about how the underlying systems can read the query that you write and parse it. We will not talk about LINQ but instead we will talk about Lambdas and Expression Trees.

Func<string, bool> test = x => x.Length > 10;
Expression<Func<string, bool>> test2 = x => x.Length > 10;

Ok, so you would be wondering what is the difference between these 2 statements. Well there is quite a lot of difference.
When the compiler grabs the first statement, it will treat this line of code like a normal delegete, producing MSIL that can “run” the specified code. Yet for the second statement the compiler will build an Expression Tree so that who ever receives the “test2” can parse the expression tree and do some work. To have a better idea of what I am saying I opened my friend Reflector and disassembled the two statements.

1st Statement

CS$<>9__CachedAnonymousMethodDelegate1 = delegate (string x) {
return x.Length > 10;
};
Func<string, bool> test = CS$<>9__CachedAnonymousMethodDelegate1;

2nd Statement

Expression<Func<string, bool>> test2 = Expression.Lambda<Func<string, bool>>(Expression.GreaterThan(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(string), “x”), (MethodInfo) methodof(string.get_Length)), Expression.Constant(10, typeof(int))), new ParameterExpression[] { CS$0$0000 });

Quite a big difference one can notice !

Basically the compiler has building up a set of objects that we can parse in order to do a unit of work. And that is the power of Lambda and Expression Trees

Now that we know that the compiler will give us an Expression tree let’s dive into some code. I will will create a method that accepts an expression and translates that expression into a URL. So for example we will have a user that wants a customer that has a name of ‘Marlon’ and we will give him ‘www.blablabla.com/Customer.aspx?Name=Marlon’

First let’s create the Customer class.

linq1.jpg

Now that we have the class let’s create a dummy method that will eventually be our URL provider.

linq2.jpg

So the method above accepts an Expression of type Func that has a Customer generic type and a bool as return type. The method will later parse the expression to form a URL out of it.

Now lets’ call this method to see how the code for the lambda would look like.

linq3.jpg

Great we have everything set up and now we can start having some fun parsing the Expression Tree (FINALLY). The expression that was passed to us contains a Body property. The body is a BinaryExpression that contains a Left property a right property and a NodeType property.
The Left property will contain the expression on the left of our lambda i.e x.Name
The Right property will contain the expression on the right of our lambda i.e “marlon”
The NodeType will contain the operation that was applied between the 2 expression (this is an ExpressionType enum ex. Equals, GreaterThan etc..)

The tree would look something like this

linqimg1.jpg

So what we need to do now is to cast the Left expression as a MemberExpression since we know that we have an expression that is accessing a Property of the object (Please note that we are doing this assumption to simplify the blog post in a Part 2 of this post I will discuss how one should recursivly cast this expression since you can have multiples). By doing so now we can access the name of the property that the lambda is calling i.e Name and we can put it in our URL. We can also cast the Right expression to a ConstantExpression that will give us the value that is on the right side of the expression i.e “Marlon”. Having said all this have a look at the code to get a better idea of what is happening

linq4.jpg

As you can see all we are doing in this method is to get the data from the expression tree and write a string accordingly. AGAIN I want to make this crystal clear, this implementation is quite Naive. There are infinite number of problems with this…. For example if the user passes an expression like this

x => x.Name == “Marlon” && x.Name == “Raffaele”

Then we would get a nice Exception because the Left Expression would not be a Member expression anymore but it would be a BinaryExpression that contains the x.Name == “Marlon” and the Right expression would be the x.Name = “Raffaele”. Something like this.

linqimg2.jpg

This can go on infinitly (or maybe until the developer gets tired writing the lambda 🙂 ) and that is why recursion is needed for parsing an expression tree. I will dive into this on my next post on Expression Trees, right now I will dive into my bed because I cannot make my eyes stay opened any longer….

So guys I hope you liked the article I will be posting Part 2 where we will implement a much more complex expression parser using some recursion and god knows what not.

Download Sample Application >>

17 thoughts on “Working with Expression Trees – Part 1

  1. A very nice post there Marlon.

    I’ve only just started to read you blog, but I like it. And will be coming back for sure.

    Keep it up man

    PS : Well done for winning the star wars light saber game

  2. Pingback: Manually constructing Expressions « C h a k s’ C o r n e r

  3. Pingback: How to effectively debug Expression Tree « Automation Planet

  4. Pingback: How to effectively debug Expression Tree? | Automation Planet

Leave a comment