my goal is to use reflection emit to construct generic type with the generic parameters of the created generic method so the end result of the created generic method is similar to
void DoSomeThing<T>(T arg){
var list=new List<T>();
}
so what I need is the code used to emit this fragment of code
new List<T>
and this is my try
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);
the exception is in this line of code
var c = list_of_T.GetConstructor(new Type[0]);
and it is caused by this line of code
var list_of_T = listType.MakeGenericType(genericPrms);
the exception is
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)
and by digging in (MakeGenericType) method, it returns a new instanse of TypeBuilderInstantiation if any of the parameter types isn't a (RuntimeType)
the type TypeBuilderInstantiation is nothing but an empty implementation of the abstract type 'TypeInfo' [whis is an abstract impl. of the type 'Type'], which all of its method throwing not supported exception
my goal is not to create a method to return new List, it's more complicated than that, but my obstacle is the same as doing so.
thanx for helping.
Yeah, there's definitely a trick to this. Indeed you cannot call any methods on the TypeBuilderInstantiation
. Instead, TypeBuilder
will let you get constructors for dependent types.
The
GetConstructor
method provides a way to get aConstructorInfo
object that represents a constructor of a constructed generic type whose generic type definition is represented by aTypeBuilder
object.
https://msdn.microsoft.com/en-us/library/ms145822(v=vs.110).aspx
You first need the generic ConstructorInfo
, gotten from typeof(List<>)
in the usual way...
var listDefaultConstructor = listType.GetConstructor(new Type[0]);
and then instantiate it to your particular generic implementation:
var c = TypeBuilder.GetConstructor(list_of_T, listDefaultConstructor);
Whenever you would like to call a method on an instance of Type
that represents an unconstructed/dependent type, instead look for a method with the same name in the Reflection.Emit hierarchy.
Among other things, this design pattern of passing in the generic version of the MethodInfo
allows you to distinguish between calls to overloaded Class<T=int>.Foo(T)
and Class<T=int>.Foo(int)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With