创建DynamicMethod以调用构造函数

时间:2014-10-21 01:26:32

标签: c# c#-4.0 reflection.emit

我试图比较调用编译时未知类型的构造函数的各种方法。我有四种方法:直接调用构造函数(用于计时比较),调用ConstructorInfo.Invoke,调用Expression.Lambda.Compile,并调用Activator.Create。我无法工作的是使用DynamicMethod。以下是我的代码的一小部分示例:

public struct Foo {
    private int _val;
    public Foo(int val) {
        _val = val;
    }
    public override string ToString() {
        return _val.ToString();
    }
}

static void Main(string[] args) {
    var ctorInfo    = typeof(Foo).GetConstructor(new[] { typeof(int) });
    var ctorDynamic = new DynamicMethod("CreateFoo",
            typeof (Foo), new[] {typeof (int)});

    var ilGenerator = ctorDynamic.GetILGenerator();
    // Load the int input parameter onto the stack
    ilGenerator.Emit(OpCodes.Ldloc_0);
    // Call the constructor
    ilGenerator.Emit(OpCodes.Call, ctorInfo);
    // Return the result of calling the constructor
    ilGenerator.Emit(OpCodes.Ret);

    // Create a delegate for calling the constructor
    var ctorInvoker = (Func<int, Foo>)ctorDynamic.CreateDelegate(
                      typeof(Func<int, Foo>));

    // Call the constructor
    var foo = ctorInvoker(5);
}

当我尝试在最后一行调用构造函数委托时,我得到一个VerificationException,说“操作可能会破坏运行时的稳定性”。我想我错过了一个或多个操作码,但不知道哪个操作码。有没有人知道使用DynamicMethod执行此操作的正确方法?

1 个答案:

答案 0 :(得分:3)

当尝试编写IL时,最好的选择通常是编写等效的C#代码,然后查看生成的IL。

所以,你写一个像这样的方法:

static Foo f(int i)
{
    return new Foo(i);
}

IL看起来像:

ldarg.0
newobj      Foo..ctor
ret

这显示了您犯的两个错误:

  1. 要加载方法参数,请使用ldargldloc仅用于本地变量。
  2. 您需要使用newobj来调用构造函数,构造函数的行为不像Foo - 返回方法。
  3. 如果您修复了这些错误,您的代码就可以正常运行。

相关问题