Faster invoke method of unknown objects with Expression tree part2

In the last post I described a technique that uses Expression Tree to invoke dynamically methods of objects of types unknown at compile time. You can use this technique to build the ExpressionTreeReflection class.

You can now write code like this

1
2
3
4
5
6
7
8
private static readonly Type suType = Type.GetType("DotNetMarche.Common.Test.AuxClasses.SimpleUnknown, DotNetMarche.Common.Test");
private static readonly Object suInstance = Activator.CreateInstance(Type.GetType("DotNetMarche.Common.Test.AuxClasses.SimpleUnknown, DotNetMarche.Common.Test"));
[Test]
public void TestFuncNoArgInt32()
{ 
    Func<Object, Int32> func = ExpressionTreeReflection.ReflectFunction<Int32>(suType, "AMethod");
    Assert.That(func(suInstance), Is.EqualTo(1));
}    

You load a type unknown at compile time, the only information you know is the signature of one of its method, in the example is called AMethod and accepts no parameters and returns an Int32. The ReflectFunction() method of ExpressionTreeReflection helps you to build a Func<Object, Int32> you can use to call the method. This function accepts as first argument an instance of the object that contain the method to invoke, then all needed parameters. The first advantage is that you have a more strongly typed way to dynamically invoke the function instead of using reflection. Here is the code that invoke a function that need a string parameter.

1
2
3
4
5
6
7
[Test]
public void TestFuncOneArgInt32Overload()
{
   Func<Object, String, Int32> func = 
      ExpressionTreeReflection.ReflectFunction<String, Int32>(suType, "BMethod");
   Assert.That(func(suInstance, "test"), Is.EqualTo(8));
}    

Using the func object is really simpler than using a MethodInfo, but the real power is showed by this little test

1
2
3
4
5
6
7
8
9
[Test, Explicit]
public void TestPerformanceGain()
{
    Func<Object, Int32> func = ExpressionTreeReflection.ReflectFunction<Int32>(suType, "AMethod");
    MethodInfo minfo = suType.GetMethod("AMethod", BindingFlags.Public | BindingFlags.Instance);
    Double RefDuration = With.PerformanceCounter(() => { for (Int32 I = 0; I < 100000; ++I) minfo.Invoke(suInstance, new Object[] { }); });
    Double ExpDuration = With.PerformanceCounter(() => { for (Int32 I = 0; I < 100000; ++I) func(suInstance); });
    Console.WriteLine("Reflection = {0} Expression Tree {1}", RefDuration, ExpDuration);
}    

The timing is output in seconds and the result is.

Reflection = 0.112139753757862 Expression Tree 0.00207625064646903

You can check that with expression tree you can invoke method of unknown object faster than standard reflection.

alk.

Tags: .NET Framework Expression Tree

DotNetKicks Image