Expression Tree vs reflection
Everyone knows that invoking method through reflection is slower than direct invocation, here is a little test.
|
|
This snippet creates an object with an int property, then it make a simple increment of the property, the first time with standard code, the second time with reflection, every iteration needs two invocation through reflection, one to get the actual value, the other to set the new value, here is the output.
Direct invocation 100000 iterations 2 ms
Reflection invocation 100000 iterations 1307 ms
This simple example shows that reflection is really, really slower, but reflection makes possible to modify a property whose name is known only at runtime, so it is unavoidable in certain situation.
A simple alternative approach exists, it relay on using Expression Trees. For those who does not knows Expression Trees I suggest reading this book, in short an expression tree is simple a way to represent an expression through an object model. Now lets look at this code.
|
|
The code seems really complicated but it is simple once you knows the structure of an expression tree. We need to represent the expression obj.Prop = obj.Prop + 1, but if you try to convert this into an expression you see that the compiler generates the error An expression tree may not contain an assignment operator, but this is not a problem, because obj.Prop = something means calling the setter method of the property. Armed with this knowledge I create two distinct expression, one for the Get part and the other for the Set part. The good thing of having an ExpressionTree is that he has a method called Compile(), that creates a code block that represents the expression. In line 15 16 I use this functionality to create two delegate.
Now the fun part, suppose you does not known the type at compile time (in the code included with this post I created a type on different assembly) you can still apply this technique.
|
|
In line 1 I get the type through reflection, and in line 2 get the property Prop with reflection too. Now I begin to create the expression I need for the Getter. If I want to get a property from an object that I do not know at compile time, I need to create a function of type Func<Object, Int32> , a function that gets an object and return an Int32 value, since the property is Int32. In line 4 I create the parameter for the expression of type object, then I create a Convert expression in line 5 (it is a cast) then I create the lambda that access the property. Finally I use the Compile method to obtain a Func<Object, Int32>.
This expression is the same of this instruction ((OtherMyObject) obj).Prop but since I does not know the type at compile time Expression Tree is the only way to write such a function. The setter part is similar, you can check on the source code. The fun part is that now I can write this code.
|
|
The instance is created with Activator.CreateInstance because I really does not know the type at compile time, but I can use dynamicGetter and dynamicSetter with no problem. Here is the output of the timing.
|
|
You can see that the using this technique permits to completely bypass performance penalties that you have with reflection.
Source code can be found here.
alk.