In one of my previously published article (very old 🙂 one), I mentioned briefly about reflection, and discuss how reflection is an important concept in .Net Framework. While it is a very important concept there is a performance issue related with the Reflection. If you over use reflection codes in your projects you have to face with performance issues compared with the code that is implemented in this sample project.

In that context, I have explained two methods to have a better performance when manipulating objects dynamically and I have shared code examples about them. As a summary, I created a ObjectCreateMethod class which uses DynamicMethods and creates an IL which calls type constructors. By calling that generated DynamicMethod we can create instance of types faster than traditional reflection. If you are interested in and need more information, you can access article from here.

After reviewing previous article, now you are ready to get more information about the usage of the DynamicMethods that improve the performance of traditional reflection which is the subject of this article.

In the previous article, maybe you have discerned an imperfection. The ObjectCreateMetod class – which uses DynamicMethods for creating instance of a type – is only suitable for creating instance of types which has parameter-less constructors.

While I was surfing the web, I found a feedback about my article. Someone asks if it is possible to use ObjectCreateMethod class with types which has parameterized constructors. Because of this, I decided to updated my code, and now it also supports the constructors with parameter(s).

To resolve this issue I created a dynamic method which takes object[] argument as the constructor arguments. Than I take these parameters on to the stack and call new opcode. Here is the code;

/// <summary>
///  Creates the dynamic proxy method which calls given <see cref="ConstructorInfo"/>
/// </summary>
/// <param name="methodInfo"></param>
private static DynamicMethodDelegate CreateProxyMethod(ConstructorInfo constructor)
{
    var method = new DynamicMethod(constructor.DeclaringType.Name + "_ctor_Proxy",
        typeof(object),
        new Type[] { typeof(object[]) },
        constructor.DeclaringType);

    var wrapper = new ILGeneratorWrapper(method.GetILGenerator());

    var parameters = constructor.GetParameters();
    var parameterTypes = new Type[parameters.Length + 1];
    parameterTypes[0] = constructor.DeclaringType;
    for (int i = 0; i < parameters.Length; i++)
    {
        parameterTypes[i + 1] = parameters[i].ParameterType;
    }

    wrapper.DeclareLocals(parameterTypes);

    for (int i = 1; i < parameterTypes.Length; i++)
    {
        wrapper.EmitLoadArg(0);
        wrapper.EmitLoadCons(i - 1);
        wrapper.Emit(OpCodes.Ldelem_Ref);
        wrapper.EmitCast(parameterTypes[i]);
        wrapper.EmitStoreLocal(i);
    }

    for (int i = 1; i < parameterTypes.Length; i++)
    {
        wrapper.EmitLoadLoc(i);
    }

    wrapper.Emit_NewObj(constructor);

    wrapper.EmitStoreLocal(0);
    wrapper.EmitLoadLoc(0);
    wrapper.Emit(OpCodes.Ret);

    return method.CreateDelegate(typeof(DynamicMethodDelegate)) as DynamicMethodDelegate;
}

I also added some other helper proxy classes which provides invoking other type members (fields, properties and methods) by using DynamicMethods too.

Project has 4 proxy classes which you can use as follows;

  • RuntimeConstructorProxy: Generates a dynamic method for invoking both parameter-less and parameterized constructors of a type to create instance of the type dynamically.
    var type = typeof(Test);
    var constructorInfo = type.GetConstructor(new Type[] { typeof(int) });
    
    var proxy = (RuntimeConstructorProxy)constructorInfo;
    var result = proxy.Invoke<Test>(2);
    
    Assert.AreNotEqual(null, result);
    Assert.AreEqual(2, result.ValueTypeProp);
  • RuntimeMethodProxy: Generates a dynamic method for invoking a type method dynamically. It supports both static and instance methods.
    var type = typeof(Test);
    var instance = new Test();
    var methodInfo = type.GetMethod("Method1");
    
    var proxy = (RuntimeMethodProxy)methodInfo;
    var result = proxy.Invoke<int>(instance, null);
    
    Assert.AreEqual(1, result);
  • RuntimeFieldProxy: Generates dynamic methods for getting and setting value of a type field dynamically. It supports both static and instance fields.
    var type = typeof(Test);
    var instance = new Test();
    var fieldInfo = type.GetField("PublicValueType");
    
    var proxy = (RuntimeFieldProxy)fieldInfo;
    var result = proxy.GetValue<int>(instance);
    Assert.AreEqual(1, result);
    
    proxy.SetValue(instance, 5);
    Assert.AreEqual(5, instance.PublicValueType);
  • RuntimePropertyProxy: Generates dynamic methods for getting and setting value of a type property dynamically. It supports both static and instance properties. It also supports indexed properties too.
    var type = typeof(Test);
    var instance = new Test();
    
    var propertyInfo = type.GetProperty("InstancePublicValueType");
    var proxy = (RuntimePropertyProxy)propertyInfo;
    var result = proxy.GetValue<int>(instance);
    Assert.AreEqual(1, result);
    
    proxy.SetValue(instance, 5);
    Assert.AreEqual(5, instance.InstancePublicValueType);

Here is a performance benchmark results; As you can see our proxy classes has better performance than traditional reflection.

Performance Benchmark

Performance Benchmark

If you are interested in full project, I have shared the code with in my git-hub account. Here is the link.

PS: Because of the ref and out keywords are not supported in my code, you will get an error if you try to use RuntimeMethodProxy with methods which has ref or out parameter(s).

Share: