反射生成的类型和泛型类型
本文关键字:泛型类型 类型 反射 | 更新日期: 2023-09-27 18:05:55
我在Reflection.Emit
和类型管理方面又遇到了麻烦。
假设我有一个名为MyType
的类型,它是在动态生成的程序集中定义的。调用MyType.GetMethods()
会导致NotSupportedException
,这使我不得不编写自己的包装器和查找表集。然而,当我在使用我自己的类型作为泛型参数的标准泛型类型上调用GetMethods()
或任何其他自省方法时,也会发生同样的情况:
-
Tuple<int, string>
=>工作正常 -
Tuple<int, MyType>
=>异常
我可以从泛型类型定义中获得方法列表:
typeof(Tuple<int, MyType).GetGenericTypeDefinition().GetMethods()
然而,这些方法有泛型占位符而不是实际值(如T1
, TResult
等),我不想再编写另一个将泛型参数追溯到其原始值的汇编。
代码示例:
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<,>);
var tuple = tupleType.MakeGenericType(new [] { typeof(int), aType });
tuple.GetProperty("Item1"); // <-- here's the error
问题是:
- 我如何检测如果一个类型是安全的调用
GetMethods()
和类似的方法? - 如果类型不安全,我如何获得方法及其泛型参数值的实际列表?
我在后续问题中得到了答案。TypeBuilder
类有一堆静态重载,它们做的事情:
var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());
奇怪的是,GetProperty
没有过载。但是,属性getter和setter仍然可以使用GetMethod
:
var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);
请参考文档:
用反射发出定义类型
表示尽管TypeBuilder是从Type派生出来的,但是Type类中定义的一些抽象方法并没有在TypeBuilder中完全实现。这些TypeBuilder方法抛出NotSupportedException异常。可以通过使用type检索创建的类型来获得所需的功能。GetType或程序集。GetType,并反映检索到的类型
:
我如何检测一个类型是否可以安全地调用GetMethods()和类似的方法?
如果类型对象是TypeBuilder,或者该类型引用了任何TypeBuilder类型,那么这样做是不安全的。
如果类型不安全,我如何获得方法及其泛型参数值的实际列表?
我建议你再看一遍文档。实际将类型发出到程序集中,然后将其从程序集中取出。