Another beacon in a sea of expressions

A prosaic introduction to the subject of .NET expressions. These were introduced with .NET 3.5 and are featured most prominently in LINQ. Over here I implemented a use case with the aid of expressions.

In my current project I am using expressions to be able to analyze what the user of some API wants to express. From the expression

Expression<Function<Person,object>> e = p => p. FirstName + "," + p.LastName

I want to know that properties FirstName and LastName are being used to generate the return value. While developing the things for this to work I came across two things that really helped me:

A debugger visualizer for expressions

There is one available as part of the Visual Studio samples (under Microsoft Visual Studio 9.0\Samples\1033\CSharpSamples.zip\LinqSamples\ExpressionTreeVisualizer) or downloadable from here.

You will need to compile the visualizer and place it under VS9.0\Common7\Packages\Debugger\Visualizers.

visualization of a simple expression

The expression Visitor

At the end of this post here on The Wayward Weblog. I have taken exactly that code and just made a run with R# over it. Grab it over here. The class is extremely useful when you are checking up on complex expression trees. The class ensures that all nodes of the tree are visited and that you can actually replace certain parts of it.

You would typically create a class that inherits from the ExpressionVisitor, override the methods that are interesting to you and provide some entry point that accepts an expression which is subsequently passed to the protected base class’s Visit method.

As an example, I wanted to parse an expression that gets a DataSet as arguments and represents access to a number of fields on a number of rows stemming from said DataSet. In this case I was only interested in any MemberAccess and it was sufficient to just override that method and insert my logic:

protected override Expression VisitMemberAccess(MemberExpression m)
{
  if (m.Member.DeclaringType.IsSubclassOf(typeof (DataRow)) &&
      !m.Type.IsSubclassOf(typeof (DataRow)))
  {
    datasetFieldName = m.Member.Name;
    tableName = m.Member.DeclaringType.Name.Replace("Row", "");
  }
  else if (m.Member.DeclaringType.IsSubclassOf(typeof (DataSet)))
  {
    dataSetName = m.Member.DeclaringType.Name;
    entryTable = m.Member.Name;
  }
  persistField();
  return base.VisitMemberAccess(m);
}

As a last example, to show off the tree modifying features of the class to change an expression, the following 2 methods change

Expression<Func<SomeDataSet,object>> e = ds => ds.Master[0].FirstName + "," + ds.Master[0].GetAddresses()[0].City; to Expression<Func<DataRow,object>> e = r => ((MasterRow)r).FirstName + "," + ((MasterRow)r).GetAddresses()[0].City;

protected override Expression VisitMethodCall(MethodCallExpression m)
{
  if (m.Method.Name == "get_Item")
    return Expression.Convert(dataRowParameter, m.Type);
  return base.VisitMethodCall(m);
}

protected override Expression VisitLambda(LambdaExpression lambda)
{
  if (visitedMainLambdaBody) 
    return base.VisitLambda(lambda);
  visitedMainLambdaBody = true; // sort of. This is somewhat recursive...
  Expression body = Visit(lambda.Body);
  List<ParameterExpression> @params =
    new List<ParameterExpression> { dataRowParameter };

  return Expression.Lambda<Func<DataRow, object>>(body, @params);
}

Chronology

  |  
comments powered by Disqus