将局部变量加载到堆栈中,以便在生成IL时调用方法



我试图生成IL来模仿以下方法MyMethod:

public void DoSomething(object a, object b, string c, string d){...};
public virtual void MyMethod(object a, object b) 
{
    DoSomething(a, b, "hello", this.SomeInstanceString);
}

这是我到目前为止得到的,但我无法理解正确的方式来加载第三和第四个参数到堆栈调用DoSomething(a, b, "hello", this.SomeInstanceString)):

 MethodBuilder myMethod = typeBuilder.DefineMethod("MyMethod",
    MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new[] 
       { typeof(object), typeof(object) });
 ILGenerator myMethodILGen = mbFromCustomObject.GetILGenerator();
 myMethodILGen.Emit(OpCodes.Ldarg_0);
 myMethodILGen.Emit(OpCodes.Ldarg_1);
 // How do I load the string "hello" and the local instance 
 // variable this.SomeInstanceString onto the stack?
 myMethodILGen.Emit(OpCodes.Call, GetMethodInfoForDoSomething());
 myMethodILGen.Emit(OpCodes.Ret);

那么,我如何将字符串"hello"和本地实例变量this.SomeInstanceString加载到堆栈上以调用DoSomething呢?

加载字符串文字相当容易。

myMethodILGen.Emit(OpCodes.Ldstr, "hello");

从对象实例中加载字段需要首先将对象实例加载到堆栈中,然后使用ldfield操作码。你应该为你的SomeInstanceString字段已经有一个FieldBuilder,你可以使用它。

FieldBuilder fieldBuilder = typeBuilder.DefineField(
                    "SomeInstanceString",
                    typeof(string),
                    FieldAttributes.Public);
myMethodILGen.Emit(OpCodes.Ldarg_0);
myMethodILGen.Emit(OpCodes.Ldfld, fieldBuilder);

另外,请记住Ldarg_0 并不像您认为的那样做。实例方法有一个隐式参数,该参数位于零槽中,其中包含方法当前在其中操作的实例。这就是为什么我们使用Ldarg_0来解引用字段,因为您可能想要方法所在的实例。但是,这不适用于静态方法。

相关内容

  • 没有找到相关文章