Click here to Skip to main content
Click here to Skip to main content

C# Properties and Expression Trees

By , 4 Aug 2010
 

Expression trees in C# fascinate me. They can be used to create dynamic methods or, in some cases, wrap existing methods or properties. Once constructed as lambdas, the expressions can be executed like any other C# method. Reflection accomplishes a similar goal without using the expansive verbosity of expressions. Expressions can be thought of as a language within a language; allowing developers to programmatically create C# constructs from any source: a domain specific language, XML, etc. The power of expressions is virtually limitless… but that’s not what this post is about. In this post, I'd like to show some useful examples of expression usage, specifically calling properties.

A C# property is just syntactic sugar for getters and setters (methods that return a value and accept a single parameter). Once compiled, a property call (setter) will take on the form of set_X.

image

So if we want to use expression trees to invoke the setter, we need to use the Expression.Call(..) construct. Expression.Call when compiled into a delegate, executes on an instance. So before we create the expression, let’s first create a simple class with a single method (you can also do this with anonymous types).

public class TestClass
{
    public string Name { get; set; }
}

Pretty simple class with one property of type string. Now let’s create an expression to set a value on the property on an instance of TestClass.

TestClass t = new TestClass(); 
// Get the actual setter method.
MethodInfo info = t.GetType().GetProperty("Name").GetSetMethod(); 
// Create a parameter for the method call expression.
ParameterExpression param = Expression.Parameter(typeof(string), "val"); 
// Create a method call expression.
// The expression will be .call <instance>.set_Name(val), 
// where val is the parameter to the method.
MethodCallExpression call = Expression.Call(Expression.Constant(t), info,
    new ParameterExpression[] { param }); 
// Create a delegate whose implementation is the expression we just created.
// An Action is a delegate that takes a single parameter and returns void.
// Create a Lambda expression whose body is the MethodCallExpression 
// that takes a single parameter.
// The parameter will be passed at run time.
Action<string> action = Expression.Lambda<Action<string>>(call, param).Compile(); 
// Call the delegate (execute the expression).
action("hi"); 
// Proof we actually set the property.
Console.WriteLine(t.Name);

We'll invoke the delegate (supplying a parameter), then print the value of the property to the console. As you'd expect, it prints “hi.”

image

This all begs the question: why on earth would you want to do this? Well, for most practical purposes, it’s obviously easier to just call a property on an instance when you want to set something. But what if you have cascading expressions? What if you need to create an expression-tree to represent dynamically created methods? With the expression API, you can build an interpreter of a custom language, for instance. I believe the future of C# lies in the Expression API and the DLR. In a future entry, I will examine the DLR and expressions more closely by building a small dynamic proxy engine using method call expressions and the dynamic keyword.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

thebacon
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 4 Aug 2010
Article Copyright 2010 by thebacon
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid