在我的应用程序中,我需要动态创建包含多个属性的类型。我知道,在这样的情况下,必须使用iLgenerator生成属性的ciL和setter方法。

通过反复试验,我终于到达了以下代码,该代码为我生成了一个六元的方法:

MethodBuilder setMethod = customTypeBuilder.DefineMethod(propertyName + "_set", MethodAttributes.Public | MethodAttributes.HideBySig, null, new Type[] {propertyType});
ILGenerator setIlGenerator = setMethod.GetILGenerator();
setIlGenerator.Emit(OpCodes.Ldarg_0);
setIlGenerator.Emit(OpCodes.Ldarg_1);
setIlGenerator.Emit(OpCodes.Stfld, backingField);
setIlGenerator.Emit(OpCodes.Ret);

该代码运行得足够好,但是我对此不了解一件事。 为什么需要调用“ LDARG_0”指令?

我知道它是指该方法的隐式第一个参数,即“此”参考,因此设置器的实际值存储在第二个参数中。我认为仅调用LDARG_1指令就足够了,这将第二个参数将堆栈推向堆栈(最后,在Setter中,我不需要检查“此”参考对此进行任何操作),但是这会导致当我尝试设置属性值时,抛出了targetInvocationException。

谢谢!

有帮助吗?

解决方案

如果您没有将“此”值推到堆栈上,该如何将如何 Stfld 知道要更改哪个对象字段?您可能正在尝试编写这样的二传手:

public int Bizarre
{
    set { otherObject.Field = value; }
}

基本上, Stfld记录 要在堆栈上需要两个值:一个用于新值的“目标”,一个用于值本身。诚然,ECMA 335中的堆栈过渡图更清晰:

…, obj, value => …,

换句话说:“ STFLD将在堆栈中弹出前两个元素”。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top