Saturday, November 8, 2008

Use expression tree to avoid string literals in reflecting code part 2 (WorkflowArguments, WorkflowOutputParameters, Mapper)

Last time I was writing about a utility class called ReflectionHelper, this time I'll show you two real scenarios where this class or just expression tree have been used.

For last couple of months I've been working on a project built on the top of Workflow Foundation. Now we have C#3.0 many thinks can be done smarter, simpler, quicker, better or ... more cool ;) Let's look at a simple workflow class:

class MyWorkflow : SequentialWorkflowActivity
{
    public int MyInt { get; set; }
    public string MyString { get; set; }            

    public MyWorkflow()
    {
        CodeActivity codeActivity = new CodeActivity("codeActivity1");
        codeActivity.ExecuteCode += delegate
        {
            Console.WriteLine("MyInt : " + MyInt);                    
            Console.WriteLine("MyString : " + MyString);
            MyInt++;
            MyString = "yo";
        };
        Activities.Add(codeActivity);
    }
}

I know that not all of you had the opportunity to use WF so I'll try to give you some basics. The most elementary component in WF is an activity. We can say that activity is just a class with 'Excute' method responsible for doing some action. Workflow process is also an activity containg another activities which are executed one by one (that's why it derives from SequentialWorkflowActivity). Our workflow has only one activity CodeActivity which raises ExecuteCode event when it's executed. Additionally our process manipulates its state stored in properties MyInt and MyString. Let's see how to start this process and initialize its state:

using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{                
    var arguments = new Dictionary<string, object>()
        {
            {"MyString", "hello"},
            {"MyInt", Math.Max(5, 10)},
        };

    WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyWorkflow), arguments);
    instance.Start();
}

The problem is that method CreateWorkflow takes a dictionary where the key is a property name and the value is a value of the property. But what if someone changes the name or the type of the property someday ? The code will compile fine but at runtime we will get an exception. Since we have C#3.0 we can very easily resolve these two problems.

var arguments = new WorkflowArguments<MyWorkflow>()
{
    { w => w.MyString, "hello" },
    { w => w.MyInt, Math.Max(5,10) }
};

WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(MyWorkflow), arguments);

public class WorkflowArguments<TWorkflow> : Dictionary<string,object>
{
    public WorkflowArguments<TWorkflow> Add<T>(Expression<Func<TWorkflow, T>> property,
        T propertyValue)
    {
        var propertyInfo = Blog.Post002.ReflectionHelper.GetProperty<TWorkflow,T>(property);
        Add(propertyInfo.Name, propertyValue);
        return this;
    }
}

The same technique we be used to process parameters after execution.

static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
    Console.WriteLine("workflowRuntime_WorkflowCompleted");
    var parameters = new WorkflowOutputParameters<MyWorkflow>(e.OutputParameters);

    Console.WriteLine(parameters.GetParameter( w => w.MyInt));
    Console.WriteLine(parameters.GetParameter( w => w.MyString));            
} 

public class WorkflowOutputParameters<TWorkflow> 
{           
    private Dictionary<string, object> Parameters { get; set; }
    
    public WorkflowOutputParameters(Dictionary<string, object> parameters)
    {           
        Parameters = parameters;
    }

    public T GetParameter<T>(Expression<Func<TWorkflow, T>> property)
    {
        var propertyInfo = Blog.Post002.ReflectionHelper.GetProperty<TWorkflow, T>(property);
        return (T)Parameters[propertyInfo.Name];
    }
}

The second example is a Mapper class. It's a quite common scenario when we map instance of class A into instance of class B. For example, we very often load some kind of DAL entity from database into memory then we map it to some kind of business entity. In many cases the shape of both types if very similar, they have the same properties/fields so the mapping code is very simple. It just transfers values of properties or fields from one object to another. Mapper class is a very simple class giving us the ability to record the mapping of two types to each other. Next we can execute mapping process specifying two instances of those classes and the direction of mapping. Lets assume that we have two types:

class CustomerDal
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Age { get; set; }            
    public char Gender { get; set; }
    public string City { get; set; }
    public string Street { get; set; }
}

class CustomerBO
{
    public int Id { get; private set;  }    // only getter
    public string Name { get; set; }        // exactly the same name
    public double Age;                      // field
    public char Sex { get; set; }           // another name
    public string Address { get; set; }     // more complicated mapping
}

Now we want to map an instance of CustomerDal type to instance of CustomerBo. Firstly we need to define how the properties of types should be transformed. Once we have it we can start mapping.

var m1 = new Mapper<CustomerDal, CustomerBO>    // A type, B type
  {
      {a => a.Id, b => b.Id, Direction.A2B},    // member of type A, member of type B, mapping direction
      {a => a.Name, b => b.Name},               // by default map in both directions
      {a => a.Age, b => b.Age},                  {a => a.Gender, b => b.Sex},
      { (a, b, d) => b.Address = a.City + " " + a.Street , Direction.A2B} 
        // code snippet executed during mapping
  };
      
var customerDal = new CustomerDal { Id = 1, Name = "Michael", 
    City = "Chicago", Street = "W Washington", Age = 25, Gender = 'M'};
    
var customerBO = new CustomerBO();
m1.Map(customerDal, customerBO);

customerBO.Name = customerBO.Name + "!";
customerBO.Sex = 'F';
customerBO.Age = customerBO.Age + 1;
         
m1.Map(customerBO, customerDal);

Again, instead of specifying mapped properties in code as string literals we use expression trees. Using expression trees is safer, cleaner and much more powerful. I showed you just two examples of real life application of ExpressionTrees that goes for beyond Linq. You saw the potential. Now imagine what you can do in your project with it.

The source code for both examples you can be found here.

Use expression tree to avoid string literals in "reflecting code" (ReflectionHelper)

Reflection is a very useful mechanism letting us build very smart and flexible solutions. It is used in many places in .Net framework, for instance in Windows Forms to identify bound members or in Workflow Foundation to pass some parameters to workflow instance and many others. Those two samples have one common thing, we have to use string literals in code to identify type members such as properties. And of course it's not a problem if the types we use are not changing, it means once specified, member won't be changed in the future. Like which shouldn't change like .net framework types (it shouldn't be change cause of backward compatibility).

Lets imagine that we bind one property of our business object to a TextBox's property Text and one day during refactoring someone else changes the name or the type of the property or even worse - deletes it. The code will compile correctly but we can't be sure how it will work at runtime because it depends on the sort of change. Maybe some exception will be thrown, maybe everything will look fine but the property won't be set after modifying text in the TextBox or maybe all will work just fine. Such bugs are very unpredictable and very hard to find. Wouldn't it be nice if we could know just after change about possible problems (compilation failed). Sometimes we know than the property is used in many places in the code, so we rename it via our IDE (for instance in Visual Studio we can choose option 'Refactor -> Rename...') and we want be sure that everything works fine. Is this possible ?

Today I'll show you a utility class called ReflectionHelper giving us the ability to realize mentioned scenario. Currently when we extract information about property via reflection we write something like this:

public class SomeClass
{
    public int InstanceProperty { get; set; }
    public static int StaticProperty { get; set; }
}

PropertyInfo property1 = typeof(SomeClass).GetProperty("InstanceProperty");
PropertyInfo property2 = typeof(SomeClass).GetProperty("StaticProperty");

With ReflectionHelper the same code can be written like this:

PropertyInfo property3 = ReflectionHelper.GetProperty((SomeClass o) => o.InstanceProperty );            
PropertyInfo property4 = ReflectionHelper.GetProperty(() => SomeClass.StaticProperty);

This is exactly what we wanted to achieve. We have created instance of PropertyInfo class without using any string literals. Now when we manually change the name of a property in one place, the code won't compile. If you rename it by 'Rename...' option in VS, code inside lambda expression will be changed too.

Now, lets see how ReflectionHelper works. ReflectionHelper is a static class with 2 methods extracting information about given property. One for static properties and one for instance. The implementation is quite short and looks like this:

public static PropertyInfo GetProperty<TObject,T>(Expression<Func<TObject,T>> p) 
{ 
    return GetPropertyImpl(p); 
}
public static PropertyInfo GetProperty<T>(Expression<Func<T>> p) 
{ 
    return GetPropertyImpl(p); 
}
private static PropertyInfo GetPropertyImpl(LambdaExpression p)
{
    return (PropertyInfo)((MemberExpression)(p.Body)).Member;
}

The key point to understand how the code works is a new feature of C#3.0 called expression trees. In new version of C# we can use lambda expression in code. There are two kinds of lambda expression where the body of the method is a single expression ( x => x.ToString() ) or one or many statements (x => {return x.ToString(); } ).

Func<int, int> expressionBody = (a) => a + 1;
Func<int, int> statementBody = (a) => { return a + 1; };

In many places we use lambda with single expression body just because it's shorter but there is a scenario when we have to use it. Generally when compiler sees lambda expression in code it's treated as an anonymous method, but lambda expression can be also used to build expression trees. Lets look at the example:

Expression<Func<int, int>> exp1 = (a) => a + 1;
Expression<Func<int, int>> exp2 = (a) => { return a + 1; }; 
// Error: A lambda expression with a statement body cannot be converted to an expression tree

Ok, but what is an expression tree actually? When compiler sees lambda with expression body not in the context of delegate type but in the context of special generic type 'System.Linq.Expressions.Expression<TDelegate>' a lot of code is generated behind the scenes.

ParameterExpression p;
Expression<Func<int, int>> exp1 = Expression.Lambda<Func<int, int>>
(
    Expression.Add // body
    (
        p = Expression.Parameter(typeof(int), "a"),
        Expression.Constant(1, typeof(int))
    ),
    new ParameterExpression[] { p } // parameters
);

The code of lambda expression is interpreted and translated into code that actually builds its structure. Use 'Expreesion Tree Visualizer' to better visualize the structure of expression tree.

When we look back to implementation of GetProperty method we can see that it takes an expression tree as a parameter. Inside the the method we make some assumptions about the structure of tree so we know exactly where information about property is stored. Of course if the structure of the tree would look differently, some exception could be thrown. The same technique can be used to extract information about fields, methods and constructors (ReflectionHelper has appropriate functionality). In case of getting information about the methods there are different ways of doing it.

public class SomeClass
{
    public void InstanceMethod(int i) { }
}

Instead of writing literal call

var method = typeof(SomeClass).GetMethod("InstanceMethod");

use ReflectionHelper like this:

var method = ReflectionHelper.GetMethod<SomeClass,int>(o => o.InstanceMethod);

or like this:

var method = ReflectionHelper.GetMethodByCall<SomeClass>(o => o.InstanceMethod(1));

The implementation looks like this:

public class ReflectionHelper
{    
    public static MethodInfo GetMethodByCall<TObject>(Expression<Action<TObject>> expression) 
    { 
        return GetMethodByCallImpl(expression); 
    }
    public static MethodInfo GetMethodByCall(Expression<Action> expression) // for static methods 
    { 
        return GetMethodByCallImpl(expression); 
    }
    private static MethodInfo GetMethodByCallImpl(LambdaExpression expression)
    {
        return ((MethodCallExpression)expression.Body).Method;
    }    
    
    public static MethodInfo GetMethod<TObject, T>(Expression<Func<TObject, Action<T>>> expression) 
    { 
        return GetMethodImpl(expression); 
    }
    public static MethodInfo GetMethod<T>(Expression<Func<Action<T>>> expression) // for static methods 
    { 
        return GetMethodImpl(expression); 
    }
    private static MethodInfo GetMethodImpl(LambdaExpression expression)
    {
        return (MethodInfo)((ConstantExpression)((MethodCallExpression)((UnaryExpression)expression.
            Body).Operand).Arguments.Last()).Value;
    }
}

When we use GetMethod method we don't need to write methods parameters inside brackets but we need to provide their types as generic method arguments (if parameters exist or method returns something). In the second approach we just write code executing method inside lambda expression. The code is never executed so we don't have to pass any correct arguments. These two approaches have one common disadvantage. When we change the signature of the method by changing parameters or return type, we need to change the code reflecting that method too. Maybe there is some solution but I couldn't find it :(

Full implementation of ReflectionHelper class with code presenting many different scenarios of using them can be found here. In the next post I'll show you how the ReflectionHelper is used in real life :) Stay tuned!