How can I get objects and property values from expression trees?

This is a follow-up to the Getting Information About Objects, Types, and Members with Expression Trees post, so I would recommend that you read that one first.

Among other code examples in that blog post, I demonstrated how you can get a property name as a string by using expression trees. Here is the method.

 public static string GetName<T>(Expression<Func<T>> e)
{
    var member = (MemberExpression)e.Body;
    return member.Member.Name;
}

And here is how you can use it.

 string str = "Test";
Console.WriteLine("{0} : {1}",
GetName(() => str.Length), str.Length);
// Prints Length : 4

When you go deep into expression trees, you may need to get the actual value of the property or the reference to the containing object out of the expression itself. I’m going to show some tricks using simple and contrived examples, but remember that scenarios when you really need to do this are usually much more advanced. (Think about LINQ providers.)

Let’s say I want to create a method that prints not only the name of a property, but also the value of the property. Such a method might look like this.

 public static void PrintProperty<T>(Expression<Func<T>> e)
{
    var member = (MemberExpression)e.Body;
    string propertyName = member.Member.Name;
    T value = e.Compile()();
    Console.WriteLine("{0} : {1}", propertyName, value);
}

Now let’s look closely at this magic line:

 T value = e.Compile()();

In general, T is the type of the value that the expression produces. To simplify the example, the code only works for expressions like 
()=>obj.Property. So in this case, T is the type of the property.

To get the property value, I need to compile this expression into a delegate and then invoke the delegate. In fact, I can write two separate lines of code instead of the shorter syntax used above:

 Func<T> del = e.Compile();
T value = del();

So far, so good. Now I have a method that prints both the property name and its value:

 string str = "Test";
PrintProperty(() => str.Length);
// Prints Length : 4

Let’s take it one step further. Suppose that I want this method to print not only the property value, but also the string itself:

 String: Test
Length : 4

How can I do this? If I have an expression like () => str.Length, I can parse it like this:

 public static void PrintPropertyAndObject<T>(Expression<Func<T>> e) 
// e represents "()=>str.Length"
{
    MemberExpression member = (MemberExpression)e.Body; 
    // member represents "str.Length"

    Expression strExpr = member.Expression; 
    // strExpr represents "str"

    . . .     
}

The object I need is now represented by strExpr. However, I can’t compile this expression into a delegate.

 String resultStr = strExpr.Compile()(); // Compiler error here.

Only lambda expressions can be compiled into delegates. The problem is that strExpr is not a lambda expression.

Luckily, there is a trick that solves this problem. You can convert expressions into lambda expressions by using the Expression.Lambda<Tdelegate>() method. So, if I have an expression that represents "str", this method converts it to "()=>str".

To use this method, I need to specify a type of the delegate for the lambda expression. ()=>str returns string, so I am going to use Func<String>here.

 // Converting the expression into a lambda expression.
Expression<Func<string>> lambdaExpr = Expression.Lambda<Func<string>>(strExpr);

Now I can compile and invoke lambdaExpr:

 // Compiling the lambda expression into a delegate.
Func<String> del = lambdaExpr.Compile();

// Invoking the delegate.
String resultStr = del();

Or I can use shorter syntax and combine these three lines of code into one:

 String resultStr = Expression.Lambda<Func<String>>(member.Expression).Compile()();

Of course, if strExpr is not a string, I get a runtime exception. But I can check whether it is a string by using the Expression.Type property.

 if (strExpr.Type == typeof(String))
{
    String str = Expression.Lambda<Func<String>>(strExpr).Compile()();
    Console.WriteLine("String: {0}", str);
}

And here is the whole method:

 public static void PrintPropertyAndObject<T>(Expression<Func<T>> e) 
{
    MemberExpression member = (MemberExpression)e.Body; 
    Expression strExpr = member.Expression; 
    if (strExpr.Type == typeof(String))
    {
        String str = Expression.Lambda<Func<String>>(strExpr).Compile()();
        Console.WriteLine("String: {0}", str);
    }
    string propertyName = member.Member.Name;
    T value = e.Compile()();
    Console.WriteLine("{0} : {1}", propertyName, value);
}

Once again, remember that this is a contrived example. I definitely would not recommend using this technique to print the value of a string object. But it might come in handy when you are debugging or analyzing complex expression trees.

Last but not least, remember that compiling expression trees is not a fast operation. So do not overuse it, or the performance of your application may degrade.

P.S.

Special thanks to Bill Chiles for patiently reading and reviewing three different versions of this post.