发出操作码将字段设置为一个值

6

我正在尝试动态创建代理,因此我在使用Emit。所以当我使用emit设置我的字段时,我还需要将isDirty字段布尔值设置为true。

我该怎么做?

Property Customer
{
  set
  {
    this.customerName = value;
    this.isDirty = true;
  }
}

发射代码:
 FieldBuilder isDirtyField = myTypeBuilder.DefineField("isDirty", typeof(bool), FieldAttributes.Private);                                                              

// Define the "set" accessor method for CustomerName.
            MethodBuilder custNameSetPropMthdBldr =
                myTypeBuilder.DefineMethod("set_CustomerName",
                                           getSetAttr,
                                           null,
                                           new Type[] { typeof(string) });

        ILGenerator custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();

        custNameSetIL.Emit(OpCodes.Ldarg_0);
        custNameSetIL.Emit(OpCodes.Ldarg_1);
        custNameSetIL.Emit(OpCodes.Stfld, customerNameBldr);

        {
            custNameSetIL.EmitWriteLine("Start isDirty");
            ... do stuf here
            custNameSetIL.EmitWriteLine("End isDirty");

        }
        custNameSetIL.Emit(OpCodes.Ret);

这段代码是可以正常工作的,只要不涉及到isDirty字段。我花了整个周末来解决这个问题,现在在论坛上寻求帮助。谢谢。
// Dennis
1个回答

9
我认为你想要的IL指令序列将是:
custNameSetIL.Emit(OpCodes.Ldarg_0);     // load this
custNameSetIL.Emit(OpCodes.Ldc_I4_1);            // load true (same as integer 1)
custNameSetIL.Emit(OpCodes.Stfld, isDirtyField); // store into isDirty

这个有效,谢谢。我在这里有一些代码,并且在emit code中有一个简单的set方法,你能告诉我为什么需要加载THIS吗?当我计算栈上的内容时,我最终会得到一个This项目,还是不会?为什么我需要加载this,我需要每次需要做某事时都这样做吗? - Dennis Larsen
1
@Dennis - 如果你在写C#,你会有类似于this.isDirty = true;的代码。在IL中也是一样的:因为你正在设置一个实例属性,所以需要指示你正在操作哪个实例。当设置字段时,Stfld操作数将从堆栈中弹出实例和值,因此你不会在堆栈上保留你的this实例。 - kvb
感谢澄清,这种低级别的编码并不容易,但我在逐渐进步,在努力理解编码的方法。 - Dennis Larsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接