Saturday, September 10, 2011

Intro to Expressions

I've been doing a lot of work with Expressions recently and completely love working with them. I feel that they allow your code to be more powerful as well as more expressive. It seems to me that many developers don't use Expressions in their code though. Maybe that is because Expressions can seem daunting. If this is the case I figured some of you might like a walk through of how you can use Expressions in your daily development.

What will we be building today? How about the beginnings a validation-helper for ensuring that a field, property, or argument is not null? How often have you written the following code?

Now this code is all good and well. But at some point we might change the name of the parameter but forget to update the string that represents the name of the parameter. Instead we can use an Expression which will dynamically get the name of the member which guarantees that the argument name provided to the ArgumentNullException constructor is always correct. So instead of using a string to represent the argument name, let's use an Expression:

Nice and simple! Now for some Expression basics.

Expression Basics

As seen on msdn the System.Linq.Expression namespace can be explained as follows:
The System.Linq.Expressions namespace contains classes, interfaces and enumerations that enable language-level code expressions to be represented as objects in the form of expression trees.

The abstract class Expression provides the root of a class hierarchy used to model expression trees.

The classes in this namespace that derive from Expression, for example MemberExpression and ParameterExpression, are used to represent nodes in an expression tree. The Expression class contains static (Shared in Visual Basic) factory methods to create expression tree nodes of the various types.

The enumeration type ExpressionType specifies the unique node types.

I think that's enough of that for now. Let's dive into some code.

Following is what our method might look like without utilizing Expressions.

As we will be passing properties, fields, and method parameters into our IsNotNull method, we will be dealing exclusively with Expressions of type MemberExpression.
The best tool in the Expression toolbox is the ExpressionVisitor. In a nutshell an ExpressionVisitor handles the navigation and of an ExpressionTree (which we will talk about in more detail in my next post).

To handle extracting the MemberExpressions from our ExpressionTree we will create an ExpressionVisitor and override the VisitMember method. The VisitMember method will simply add the MemberExpression to a SortedList instance. The reason for using a SortedList is that a single Expression Tree can contain many Expressions. In some scenarios the order of which the Expressions are extracted can be very important.Here is our CustomExpressionVisitor implementation:

Now that we have a method of extracting a MemberExpression, we can implement our IsNotNull(Expression>) method. This method must do the following:
  1. Extract the MemberExpression
  2. Extract the value of the property, field, or argument from the MemberExpression
  3. Check if the value is null
  4. If null, throw an ArgumentNullException

Here is the finished code for the Validate class:

And finally here is an example of how to invoke IsNotNull:

Source code can be downloaded from github here.