我在Reflection.Emit
和类型管理方面又遇到了一个令人讨厌的时刻。
说,我有一个名为MyType
的类型,它在动态生成的程序集中定义。
调用MyType.GetMethods()
会产生NotSupportedException
,这使我减少了编写自己的包装器和查找表的能力。但是,当我在使用我自己的类型作为泛型参数的标准泛型类型上调用GetMethods()
或任何其他内省方法时,也会发生同样的情况:
Tuple<int, string>
=&gt;工作正常Tuple<int, MyType>
=&gt;例外我可以从泛型类型定义中获取方法列表:
typeof(Tuple<int, MyType).GetGenericTypeDefinition().GetMethods()
但是,这些方法具有通用占位符而不是实际值(例如T1
,TResult
等)。我不想编写另一个将通用参数追溯到其原始版本的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
所以问题是:
GetMethods()
和类似的方法?答案 0 :(得分:7)
我在follow-up question得到了答案。 TypeBuilder
类有一堆静态重载,完全可以做到这一点:
var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());
奇怪的是,GetProperty
没有超载。但是,仍然可以使用GetMethod
解析属性getter和setter:
var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);
答案 1 :(得分:4)
我会向您推荐文档:
Defining a Type with Reflection Emit
说
虽然TypeBuilder是从Type派生的,但Type类中定义的一些抽象方法并未在TypeBuilder中完全实现。这些TypeBuilder方法抛出NotSupportedException。通过使用Type.GetType或Assembly.GetType检索创建的类型并反映检索到的类型,可以获得所需的功能。
所以:
如何检测类型是否可以安全地调用GetMethods()和类似的方法?
如果类型对象是TypeBuilder,或者类型引用的是TypeBuilder的任何类型,那么这样做是不安全的。
如果类型不安全,我如何得到实际的方法列表及其通用参数值?
我会再次向您推荐文档。实际上将类型发射到装配体中,然后将其从装配体中取出。