14

我在Reflection.Emit类型管理方面又遇到了麻烦。

比如说,我有一个名为的类型MyType,它是在动态生成的程序集中定义的。在 a 中调用MyType.GetMethods()结果NotSupportedException,这使我不得不编写自己的一组包装器和查找表。但是,当我在GetMethods()使用我自己的类型作为泛型参数的标准泛型类型上调用或任何其他自省方法时,也会发生同样的情况:

  • Tuple<int, string>=> 工作正常
  • Tuple<int, MyType>=> 例外

我可以从泛型类型定义中获取方法列表:

typeof(Tuple<int, MyType).GetGenericTypeDefinition().GetMethods()

但是,这些方法具有通用占位符而不是实际值(例如T1TResult),我不想编写另一个将通用参数追溯到其原始值的 kludge。

代码示例:

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. 如果类型不安全,如何获取方法的实际列表及其通用参数值?
4

2 回答 2

7

我在后续问题中得到了答案。该类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);
于 2013-03-28T05:53:31.373 回答
4

我会让你参考文档:

使用反射发射定义类型

它说

虽然 TypeBuilder 是从 Type 派生的,但是 Type 类中定义的一些抽象方法在 TypeBuilder 中并没有完全实现。这些 TypeBuilder 方法抛出 NotSupportedException。可以通过使用 Type.GetType 或 Assembly.GetType 检索创建的类型并反映检索到的类型来获得所需的功能。

所以:

如何检测类型是否可以安全地调用 GetMethods() 和类似方法?

如果类型对象是 TypeBuilder,或者如果该类型引用了属于 TypeBuilder 的任何类型,那么这样做是不安全的。

如果类型不安全,如何获取方法的实际列表及其通用参数值?

我会再次向您推荐文档。实际上将类型发出到程序集中,然后将其从程序集中取出。

于 2013-03-26T21:15:02.123 回答