我正在尝试生成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);
}
这是我到目前为止所做的,但是我无法理解将第3和第4个参数加载到堆栈上以调用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
?
答案 0 :(得分:4)
加载字符串文字非常简单。
myMethodILGen.Emit(OpCodes.Ldstr, "hello");
从对象实例加载字段要求您首先将对象实例加载到堆栈上,然后使用Ldfld操作码。你可能已经为你的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取消引用字段的原因,因为大概你想要方法所在的实例。但这不适用于静态方法。