使用Reflection.Emit用泛型参数实例化泛型类型

本文关键字:参数 实例化 泛型类型 泛型 Reflection Emit 使用 | 更新日期: 2023-09-27 18:14:43

我的目标是使用反射发射来构造具有所创建泛型方法的泛型参数的泛型类型因此,所创建的通用方法的最终结果与相似

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(方法,如果任何参数类型不是(RuntimeType(,它将返回TypeBuilderInstantation的新实例

类型TypeBuilderInstantation只不过是抽象类型"TypeInfo"的空实现[whis是类型"type"的抽象impl.],其所有方法抛出都不支持异常

我的目标不是创建一个返回新列表的方法,它比这更复杂,但我的障碍和这样做是一样的。

感谢thanx的帮助。

使用Reflection.Emit用泛型参数实例化泛型类型

是的,这肯定有诀窍。实际上,您不能在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);

如果要在Type的实例上调用表示未构造/依赖类型的方法,请在Reflection.Emit层次结构中查找具有相同名称的方法。


除其他外,这种传入MethodInfo的通用版本的设计模式允许您区分对重载Class<T=int>.Foo(T)Class<T=int>.Foo(int)的调用。