创建DynamicMethod以调用构造函数

本文关键字:构造函数 调用 DynamicMethod 创建 | 更新日期: 2023-09-27 18:27:10

我试图比较调用编译时未知类型的构造函数的各种方法。我有四个方法在工作:直接调用构造函数(用于定时比较)、调用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进行此操作的正确方法吗?

创建DynamicMethod以调用构造函数

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

所以,你写了一个方法,比如:

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

IL将看起来像:

ldarg.0
newobj      Foo..ctor
ret

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

  1. 若要加载方法参数,请使用ldargldloc仅用于局部变量
  2. 您需要使用newobj来调用构造函数,构造函数的行为不像Foo返回方法

如果您修复了这些错误,您的代码就会正常工作。