2013-03-27 1 views
4

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

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: Указанный метод не поддерживается.

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

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

+0

Каковы сведения об исключении? –

+0

Я добавил информацию об исключении из исходного вопроса. – Impworks

+2

Возможно, вы не прочитали последний комментарий, который я оставил вам по вашему предыдущему вопросу. Я повторю его для вас здесь: ** Reflection.Emit слишком слаб, чтобы использовать для создания реального компилятора. ** Это отлично подходит для небольших задач компиляции игрушек, таких как испускание динамических сайтов вызовов и деревьев выражений в запросах LINQ, но для сортировок проблем, с которыми вы столкнетесь в компиляторе, вы быстро превысите свои возможности. Используйте CCI, а не Reflection.Emit. –

ответ

5

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

var ctor = TypeBuilder.GetConstructor(
    tupleType, typeof(Tuple<,>).GetConstructors().Single()); 
+0

Ничего себе! Это действительно работает! Мне даже удалось получить доступ к свойствам через «GetMethod()». – Impworks