Я пытаюсь сравнить различные методы вызова конструктора типа, который неизвестен во время компиляции. У меня есть четыре метода работы: прямой вызов конструктора (для сравнения времени), вызов ConstructorInfo.Invoke, вызов Expression.Lambda.Compile и вызов Activator.Create. Тот, с которым я не могу работать, использует DynamicMethod. Вот небольшой пример моего кода:Создание DynamicMethod для вызова конструктора
public struct Foo {
private int _val;
public Foo(int val) {
_val = val;
}
public override string ToString() {
return _val.ToString();
}
}
static void Main(string[] args) {
var ctorInfo = typeof(Foo).GetConstructor(new[] { typeof(int) });
var ctorDynamic = new DynamicMethod("CreateFoo",
typeof (Foo), new[] {typeof (int)});
var ilGenerator = ctorDynamic.GetILGenerator();
// Load the int input parameter onto the stack
ilGenerator.Emit(OpCodes.Ldloc_0);
// Call the constructor
ilGenerator.Emit(OpCodes.Call, ctorInfo);
// Return the result of calling the constructor
ilGenerator.Emit(OpCodes.Ret);
// Create a delegate for calling the constructor
var ctorInvoker = (Func<int, Foo>)ctorDynamic.CreateDelegate(
typeof(Func<int, Foo>));
// Call the constructor
var foo = ctorInvoker(5);
}
При попытке вызвать конструктор делегата на последней строке, я получаю VerificationException, который говорит «Операция может дестабилизировать выполнения.» Я думаю, что мне не хватает одного или нескольких опкодов, но не знаю, какой из них. Кто-нибудь знает, как правильно это сделать, используя DynamicMethod?
Из любопытства, как вы посмотрели MSIL? Я вижу, что есть инструмент под названием ildasm, который поставляется с VS2013, но не смог найти файлы * .re, над которыми он должен работать. –
Хотя newobj будет работать, для типов значений это ненормально, поэтому вы не увидели бы вышеперечисленное, выпущенное компилятором. В документах: «Типы значений обычно не создаются с помощью newobj. Обычно они выделяются либо как аргументы, либо локальные переменные, используя newarr (для нулевых, одномерных массивов) или как поля объектов. После выделения они инициализируется с помощью Initobj. Однако инструкция newobj может использоваться для создания нового экземпляра типа значения в стеке, который затем может быть передан в качестве аргумента, сохранен в локальном и т. д. ». –
@ user960115 Да, ildasm - один из вариантов. И он работает на нормальных .Net .DLL и .EXE. – svick