2016-10-24 11 views
3

моей целью является использование отражений испускает для построения универсального типа с общими параметрами созданного универсального метода поэтому конечный результат созданного общего метода аналогиченИспользования Reflection.Emit для создания экземпляра универсального типа с Generic Параметры

void DoSomeThing<T>(T arg){ 
    var list=new List<T>(); 
} 

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

new List<T> 

и это моя попытка

 var _assemblyName = "asm.dll"; 
     var _assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(_assemblyName), System.Reflection.Emit.AssemblyBuilderAccess.RunAndSave); 
     // ApplyReflectionPermission(asm); 

     var _moduleBuilder = _assemblyBuilder.DefineDynamicModule("module", _assemblyName, true); 


     var type = _moduleBuilder.DefineType("type"); 

     var method = type.DefineMethod("DoSomeThing", MethodAttributes.Public | MethodAttributes.Static); 
     var genericPrms = method.DefineGenericParameters("T"); 
     method.SetParameters(genericPrms); 
     method.SetReturnType(typeof(void)); 


     var il = method.GetILGenerator(); 
     var listType = typeof(List<>); 
     var list_of_T = listType.MakeGenericType(genericPrms); 


     il.DeclareLocal(list_of_T); 
     var c = list_of_T.GetConstructor(new Type[0]); 


     il.Emit(OpCodes.Newobj, c); 
     il.Emit(OpCodes.Stloc, 0); 
     il.Emit(OpCodes.Ret); 
     type.CreateType(); 
     _assemblyBuilder.Save(_assemblyName); 

исключение составляет в этой строке кода

var c = list_of_T.GetConstructor(new Type[0]); 

и это вызвано этой строки кода

var list_of_T = listType.MakeGenericType(genericPrms); 

исключение составляет

System.NotSupportedException: Specified method is not supported. 
    at System.Reflection.Emit.TypeBuilderInstantiation.GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) 
    at System.Type.GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)  
    at System.Type.GetConstructor(Type[] types) 

и рыть в (MakeGenericType), он возвращает новый экземпляр TypeBuilderInstantiation, если какой-либо из типов параметров не является (RuntimeType)

тип TypeBuilderInstantiation - это не что иное, как пустая реализация абстрактного типа 'TypeInfo' [whis is abstract impl. типа «Тип»], в котором все его методы выбрасывают не поддерживаемое исключение

Я не хочу создавать метод для возврата нового списка, это сложнее, но это препятствие - это то же самое, что и в случае с этим.

thanx для оказания помощи.

+1

Это, конечно же, не убило бы их, чтобы использовать специальное сообщение об исключении типа «Указанный метод не поддерживается. Используйте TypeBuilder.GetConstructor (Type, ConstructorInfo)' –

ответ

4

Да, это определенно трюк. Действительно, вы не можете назвать какие-либо методы на TypeBuilderInstantiation. Вместо этого TypeBuilder позволит вам получить конструкторы для зависимых типов.

GetConstructor метод обеспечивает способ получить ConstructorInfo объект, представляющий конструктор построенного универсального типа, чей общий тип определения представлен TypeBuilder объекта.

https://msdn.microsoft.com/en-us/library/ms145822(v=vs.110).aspx

Сначала необходимо родовое ConstructorInfo, расставшись с typeof(List<>) обычным способом ...

var listDefaultConstructor = listType.GetConstructor(new Type[0]); 

, а затем создать его экземпляр для конкретной общей реализации:

var c = TypeBuilder.GetConstructor(list_of_T, listDefaultConstructor); 

Всякий раз, когда вы хотите вызвать метод на i nstance из Type, который представляет собой неконструированный/зависимый тип, вместо этого найдите метод с таким же именем в иерархии Reflection.Emit.


Среди прочего, это шаблон проектирования перехода в родовой версии MethodInfo позволяет различать между вызовами перегруженной Class<T=int>.Foo(T) и Class<T=int>.Foo(int).

+0

Я искал решение этой проблемы в течение 3 дней, спасибо :) –