【问题标题】:IL, emit default constructor callIL,发出默认构造函数调用
【发布时间】:2011-10-14 06:21:56
【问题描述】:

我在运行时生成新类型, 在我生成默认构造函数后,我想生成另一个带有参数的构造函数。我正在这样做:

cb = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
                    CallingConventions.Standard, new Type[] { typeof(bool) });
GenConstructorWithParameters(cb, fields, genFields);

问题是,我无法从方法 GenConstructorWithParameters 调用默认构造函数,因为 CLR 不允许我写这样的东西:

gen.Emit(OpCodes.Ldarg_0);        
gen.Emit(OpCodes.Call, cb.DeclaringType.GetConstructor(Type.EmptyTypes));//Not allowed to call .GetConstructor() on not created type!

如何调用默认构造函数?有可能吗?

tb - TypeBuilder 的实例,cb - ConstructorBuilder

【问题讨论】:

  • 糟糕,不是重复的,抱歉 :)

标签: c# .net code-generation il


【解决方案1】:

您应该将当前的ConstructorBuilder 传递给默认构造函数,而不是使用DeclaringType.GetConstructor

基本上,在构建类型时,在您可能对现有类型使用基于反射的方法的地方,您应该传入您已经使用的构建器。


原来是这样:

gen.Emit(OpCodes.Call, defaultCB);

其中defaultCB 是您在定义默认构造函数时声明的ConstructorBuilder

【讨论】:

  • @taras.roshko - 我相信 Marc 的回答,但我现在已经回复到 Call,只是将一些代码放在一起并在 Reflector 中检查。
  • 何谓“gen”?
  • @BrunoSantos - 这是 OP 在他们的问题中已有的内容。然而,从上下文来看,一个相当的好猜测是它是 ILGenerator 类的一个实例,因为它上面定义了很多 Emit 方法。
【解决方案2】:

你想要newobj:

gen.Emit(OpCodes.Newobj, cb.DeclaringType.GetConstructor(Type.EmptyTypes));

【讨论】:

  • Same NotSupportedException("在创建类型之前不支持被调用的成员。")
  • @taras - 然后保留你之前发明的 ConstructorBuilder
【解决方案3】:
Dim objCtor As ConstructorInfo = objType.GetConstructor(New Type() {})

      Dim pointCtor As ConstructorBuilder = pointTypeBld.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorParams)
      Dim ctorIL As ILGenerator = pointCtor.GetILGenerator()

      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Call, objCtor)

      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Ldarg_1)
      ctorIL.Emit(OpCodes.Stfld, xField)

      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Ldarg_2)
      ctorIL.Emit(OpCodes.Stfld, yField)

      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Ldarg_3)
      ctorIL.Emit(OpCodes.Stfld, zField)

      ctorIL.Emit(OpCodes.Ret)

Dim myDynamicType As Type = Nothing
Dim myDTctor As ConstructorInfo = myDynamicType.GetConstructor(aPtypes)
      Console.WriteLine("Constructor: {0};", myDTctor.ToString())

【讨论】:

    猜你喜欢
    • 2013-03-13
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多