反射生成的类型和泛型类型

本文关键字:泛型类型 类型 反射 | 更新日期: 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

问题是:

  1. 我如何检测如果一个类型是安全的调用GetMethods()和类似的方法?
  2. 如果类型不安全,我如何获得方法及其泛型参数值的实际列表?

反射生成的类型和泛型类型

我在后续问题中得到了答案。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类型,那么这样做是不安全的。

如果类型不安全,我如何获得方法及其泛型参数值的实际列表?

我建议你再看一遍文档。实际将类型发出到程序集中,然后将其从程序集中取出。