Загрузка локальных в стек для вызова метода в генерации IL? - PullRequest
1 голос
/ 29 сентября 2011

Я пытаюсь сгенерировать 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?

1 Ответ

4 голосов
/ 29 сентября 2011

Загрузка строкового литерала довольно проста.

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

Загрузка поля из экземпляра объекта требует, чтобы вы сначала загрузили экземпляр объекта в стек, а затем использовали код операции Ldfld. Вероятно, у вас уже должно быть FieldBuilder для вашего поля SomeInstanceString, которое вы можете использовать для этого.

FieldBuilder fieldBuilder = typeBuilder.DefineField(
                    "SomeInstanceString",
                    typeof(string),
                    FieldAttributes.Public);

myMethodILGen.Emit(OpCodes.Ldarg_0);
myMethodILGen.Emit(OpCodes.Ldfld, fieldBuilder);

Кроме того, имейте в виду, что Ldarg_0 делает не то, что вы думаете, . Методы экземпляра имеют неявный аргумент, который находится в нулевом интервале, который содержит экземпляр, в котором метод в настоящее время работает. Вот почему мы используем Ldarg_0 для разыменования поля, потому что, вероятно, вам нужен экземпляр, в котором находится метод. Однако это не относится к статическим методам.

...