Expression based Property Getters and Setters


Many times I need to get or set properties on a class dynamically, i.e.
not knowing their exact names at the compile times. Usually I was doing it
using System.Reflection API’s PropertyInfo
class. This class provides GetValue() and
SetValue methods that allow extrating or setting
a value of a C# property based on the the propertie’s name.
The problem with this approach is that accessing a property dynamically
using reflection API is very slow in comparison to accessing it
via usual static API – in my tests the difference was more than 60-fold.

I thought about using LINQ’s expression trees, instead. Nice thing about the
expression trees is that they can be compiled in a way very similar to
static compilation. It turned out that there are already examples of
Expression getters and setters available on the internet e.g. from
Using expression trees to get property getter and setters and Creating a property setter delegate.

Based on the code described at the above URL, I built my own little
Expression based getter and setter library:

// returns property getter
public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
{
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");

    Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Func<TObject, TProperty> result =
        Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();

    return result;
}

// returns property setter:
public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
{            
    ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));

    ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);

    MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);

    Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
    (
        Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
    ).Compile();

    return result;
}

I also did some benchmarking comparing the speed of these getters and setters to those of

  1. Direct statically compiled code setting and getting the properties
  2. Statically compiled lambdas
  3. Reflection based property getting and setting

Here are the results of running the getters and setters on 100000000 different objects with
string properies:

Getters

Time (seconds) Getter Type
0.4 Direct Statically Compiled
0.64 Statically Compiled Lambda
2.0 Compiled Expression based Getter
36.5 Reflection based Getter

Setters

Time (seconds) Setter Type
0.7 Direct Statically Compiled
1.0 Statically Compiled Lambda
2.4 Compiled Expression based Setter
50.6 Reflection based Setter

You can see, that even though the dynamically compiled expressions are 3-5 times slower than
statically compiled direct methods and 2-3 times slower than statically compiled lambdas,
they are 18-20 times faster than Reflection based approach.

The code for the demo is located under CompiledExpressionTests.zip

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: