Как перевести создание нового объекта?
Не так давно я начал учиться использовать пространство имен System.Reflection.Emit. Я сейчас пытаюсь перевести этот код для использования ILGenerator:
MyClass c = new MyClass("MyClass");
c.Do(":D");
Для этого куска кода у меня есть три вопроса: как создать объект? как вызвать конструктор и как вызвать метод класса? Пожалуйста помоги.
1 ответ
Вот полный пример, который показывает необходимый код IL.
Вы можете проверить это в LINQPad:
void Main()
{
// Manual test first
MyClass c = new MyClass("MyClass");
c.Do(":D");
var method = new DynamicMethod("dummy", null, Type.EmptyTypes);
var il = method.GetILGenerator();
// <stack> = new MyClass("MyClass");
il.Emit(OpCodes.Ldstr, "MyClass");
il.Emit(OpCodes.Newobj, typeof(MyClass).GetConstructor(new[] { typeof(string) }));
// <stack>.Do(":D");
il.Emit(OpCodes.Ldstr, ":D");
il.Emit(OpCodes.Call, typeof(MyClass).GetMethod("Do", new[] { typeof(string) }));
// return;
il.Emit(OpCodes.Ret);
var action = (Action)method.CreateDelegate(typeof(Action));
action();
}
public class MyClass
{
public MyClass(string text)
{
Console.WriteLine("MyClass(" + text + ")");
}
public void Do(string text)
{
Console.WriteLine("Do(" + text + ")");
}
}
Выход:
MyClass(MyClass)
Do(:D)
MyClass(MyClass)
Do(:D)
Кстати, вы можете использовать LINQPad, чтобы получить код IL для конкретного примера. Позвольте мне вырезать часть IL из приведенного выше примера, вот так (я также удалил класс, это тот же класс):
void Main()
{
MyClass c = new MyClass("MyClass");
c.Do(":D");
}
Выполнив этот код, а затем используя вкладку IL вывода, вы можете увидеть сгенерированный код:
Две инструкции stloc.0
а также ldloc.0
переменная в коде
IL, который я выпустил первым, сродни этому коду:
new MyClass("MyClass").Do(":D");
то есть. без переменных, просто временное хранилище в стеке, и действительно: