Reflection.Emit и универсальные типы

Я использую Reflection.Emit и я хочу создать тип, который будет эквивалентен следующему типу, определенному в C#:

class A
{
    public Tuple<A, int> GetValue(int x)
    {
         return new Tuple<A, int>(this, x);
    }
}

Хитрость в том, что мне нужно использовать универсальный тип из BCL, который использует мой пользовательский тип в качестве универсального аргумента.

Я возиться со следующим фрагментом:

var asmName = new AssemblyName("Test");
var access = AssemblyBuilderAccess.Run;
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, access);
var module = asm.DefineDynamicModule("Test");

var aType = module.DefineType("A");
var tupleType = typeof(Tuple<,>).MakeGenericType(aType, typeof(int));

var attrs = MethodAttributes.Public;
var method = aType.DefineMethod("GetValue", attrs, tupleType, new [] { typeof(int) });
var gen = method.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);

// here is the fail:
var ctor = tupleType.GetConstructor(new [] { typeof(int), aType } );
gen.Emit(OpCodes.Newobj, ctor);

Призыв к GetConstructor терпит неудачу со следующим исключением:

NotSupportedException: указанный метод не поддерживается.

Таким образом, в основном, это не позволит мне получить конструктор типа, который просто ссылается на мой пользовательский тип, и я не могу завершить тип до того, как будет получено тело его метода.

Неужели невозможно выйти из этого замкнутого круга?

1 ответ

Решение

По какой-то причине вам нужно использовать статическую перегрузкуGetConstructor() сделать это. В вашем случае код может выглядеть так:

var ctor = TypeBuilder.GetConstructor(
    tupleType, typeof(Tuple<,>).GetConstructors().Single());
Другие вопросы по тегам