我试图生成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来解引用字段,因为您可能想要方法所在的实例。但是,这不适用于静态方法。