C# Expression Trees!

Have you ever wondered how a property of an object can be passed to a method? I mean the property itself, not its value! Why does it matter to be able to pass a property, you might ask. Let me explain with an example. Let’s say we want to write a method that accepts a string property of an object and prints the name of the property followed by its value. How should this method be written? For the sake of demonstration, let’s suppose that we have a Person class that has two string properties, FirstName and LastName. personInstance is an instance of this class.

public Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

//... inside the main method
Person personInstance = new Person
{
    FirstName = "John",
    LastName = "Doe"
};

The goal here is to write a method PrintProperty in a way that if a property of an object is passed to it, it will print the name and the value of the property. For instance, if the method is called this way, PrintProperty(FirstName property of personInstance), it will print “FirstName: John”. Now the question is, how can we define this PrintProperty method? How can we pass the property to it?

First, let’s talk a bit about properties. In order for a property to be accessed at runtime, we need the property name and an object that has that property. Once we have this information, we can find the value of the property with help of reflection. So, the problem is now reduced to finding a way to pass an object and a property name to a method. In this post, I am going to explain three different approaches to address this problem.

Approach #1: The naive approach

We can simply pass the object and property name, and the rest can be handled by reflection.

static void PrintProperty1(object obj, string propertyName)
{
    var property = obj.GetType().GetProperty(propertyName);

    Console.WriteLine($"{propertyName}: {property.GetValue(obj)}");
}

// ... inside the main method
PrintProperty1(personInstance, "FirstName");

Here, we are using a string to identify the property. But what if at some point we decide to change the name of the property to Name instead of FirstName? Or what prevents me from passing “InvalidProperty” as the property name? There’s no way to ensure propertyName is a property of obj at compile-time.

Approach #2: Using nameof expression

Before C# 6.0, there was no good way to obtain the name of a property programmatically. But C# 6.0 introduced nameof expression that is helpful in this situation.

static void PrintProperty2(object obj, string propertyName)
{
    var property = obj.GetType().GetProperty(propertyName);

    Console.WriteLine($"{propertyName}: {property.GetValue(obj)}");
}

// ... inside the main method
PrintProperty2(personInstance, nameof(personInstance.FirstName));

As you can see, the body of PrintProperty2 is the same as PrintProperty1, what has changed, is how we pass the property name to it. Using nameof expression, if we change name of the property to Name at some point, it won’t compile. But since the parameter is string, I’m not forced to use nameof and still nothing prevents me from passing “InvalidProperty” as the property name. This approach is OK but doesn’t look cool to me. Since what we are trying to achieve, is to pass the FirstName property to the method, wouldn’t it be better if we could simply pass personInstance.FirstName? Well, the answer is we can, somehow! Expression trees are here to help! Before moving on to the third approach, let’s talk about expression trees a bit.

You can be a C#/.net developer for years and have never heard of expression trees. Before explaining expression trees, I am going to ask you a simple question to test your knowledge of expression trees. Let’s assume that we’re going to assign the following lambda expression to a variable named x. obj is an object of a class that has an int property named prop. What kinds of possible types can replace var keyword below?

var x = () => obj.prop;

If your answer to this question does not include Expression<Func<int>>, you are probably ignorant of expression trees!

Normally, when you assign an expression, a+b for instance, to a variable x, the expression is computed and its value is assigned to x. So, after it is assigned, x only knows the computed value and has no idea how the value is computed, therefore if you change the value of a, the value of x won’t change. It’s not the same for lambda expressions. If you assign a lambda expression, let’s say () => a + b, to a variable f, the value a+b is not computed at first. In contrast to the previous case, where the value got computed and stored in x, here, the instruction to produce the value is stored in f. Strictly speaking, f captures variables a and b and every time it gets invoked, it adds these two variables and returns the value. With the help of expression trees, you can create and manipulate these instructions.

Cool as it may sound, it seems hard to find a real-world situation in which expression trees can come in handy. You might be surprised by the fact that how expression trees are being used in LINQ to Sql. For instance, Where extension method that is applied to IEnumerable<T> and Where extension method that is used for IQueryable<T>, although look similar in usage and name, accept different type of parameters. Former expects a Func<T, bool> as the first parameter while the latter expects a Expression<Func<T, bool>>. You can learn more about this usage here.

Now, let’s see how expression trees can help us solve our main problem!

Approach #3: Expression Trees!

As I mentioned above, we can just pass personInstance.FirstName to the method. But if we do so, what the method will get is the value of personInstance.FirstName which is string “John”. So, we can instead pass () => personInstance.FirstName as an expression to the method and analyse it to find the object and its property member.

() => personInstance.FirstName as an Expression, is a LambdaExpression, it has a Body property that defines what the lambda expression will return. The Body property in this case is a MemberExpression - since we are trying to access a member of another expression using the dot operator. The member expression itself has an Expression property, which defines the expression that we are trying to access its member and a Member property. Member property of the MemberExpression is a MemberInfo object that has a Name property, which in this case is “FirstName”. There is an implicit level of member accessing here. Since personInstance is defined inside the main method, it cannot be accessed elsewhere, hence, the lambda expression will capture the personInstance object and store it inside a compiler-generated class as a field named personInstance. So personInstance object is a property inside an implicit compiler-generated class. As a result Expression property of the member expression, in this case, is also a MemberExpression with its Member property being a MemberInfo with personInstance name and its Expression being a ConstantExpression that has that compiler-generated class as its value. Following diagram demonstrates how the expression tree of this simple lambda expression will look like.

expression tree Expression tree of () => personInstance.FirstName (the diagram is made using draw.io)

Now we can use the above information to implement PrintProperty3 method.

static void PrintProperty3(Expression<Func<string>> propertyExpression)
{
    var memberExpression = propertyExpression.Body as MemberExpression;
    var implicitMemberExpression = memberExpression.Expression as MemberExpression;
    var objectName = implicitMemberExpression.Member.Name;
    var constantExpression = implicitMemberExpression.Expression as ConstantExpression;
    var owner = constantExpression.Value;

    var obj = owner.GetType().GetField(objectName).GetValue(owner);
    var property = memberExpression.Member as PropertyInfo;

    Console.WriteLine($"{property.Name}: {property.GetValue(obj)}");
}

// ... inside the main method
PrintProperty3(() => personInstance.FirstName);

In this approach, the method body is longer compared to the ones in previous approaches. However, when it comes to using it, passing the property is more straightforward. We can feel that we’re actually passing a property. In this case if we decide to rename FirstName property to Name we will get a compilation error. This approach is not completely safe though, we can pass () => “Hello” as the parameter! But at least we’re not relying on strings to specify properties. I personally prefer not to use nameof expression unless there is no better choice.

We just learned a new technique to specify properties. In the next part I’ll explain how this technique can be used in WPF/Xamarin.Forms applications. If you don’t know or care about WPF or Xamarin.Forms you can skip this part.

Applications in WPF/Xamarin.Forms

XAML-based technologies in C# like WPF or Xamarin.Forms, provide an ICommand interface to implement command design pattern. It is common among developers to use a single DelegateCommand -or RelayCommand– class to create new commands instead of creating a new class and implementing ICommand for each new command. Let’s assume that you have a sign up form. There is a “I Agree to the Terms” checkbox that is bound to a bool property named Agreed in your view model. There is also a button that must be disabled if the checkbox is not checked. You create your command inside your view model this way:

// define SubmitCommand property inside the view model
DelegateCommand SubmitCommand { get; set; }

// ... inside the constructor
this.SubmitCommand = new DelegateCommand(this.Submit(), () => this.Agreed);

Obviously, the submit button on your form must be bound to SubmitCommand property. This way, even if you check the checkbox, you’ll notice that the button won’t be enabled. That’s because the button won’t automatically check your CanExecute command to see if it’s changed. If your CanExecute function depends on some of the properties in your view model, you should fire CanExecute event of DelegateCommand manually every time one of these properties is changed. It’s fine to add this.SubmitCommand.RaiseCanExecuteChanged() to the getter of Agreed property. But suppose that you have many commands that depend on Agreed property and also your SubmitCommand depends on some other properties. You’ll end up with ugly getters, and it would become a headache to manage their relations. However, you can take advantage of INotifyPropertyChanged interface and use the technique explained above to tell your commands to observe the properties. You can implement a method in your DelegateCommand class to watch for property changes. And then you can simply initialize your SubmitCommand this way:

this.SubmitCommand = new DelegateCommand(this.Submit(), () => this.Agreed);
this.SubmitCommand.ObservesProperty(() => this.Agreed);

And you’re done.

As a bonus, the Prism library has a nice implementation of DelegateCommand class with an ObservesProperty method. You can check it out on their github.