Reflection-generated and generic types

不羁岁月 提交于 2020-01-23 04:44:36

问题


I'm having yet another nasty moment with Reflection.Emit and type management.

Say, I have a type named MyType which is defined in the dynamically generated assembly. Calling MyType.GetMethods() results in a NotSupportedException, which has reduced me to writing my own set of wrappers and lookup tables. However, the same is happening when I'm calling GetMethods() or any other introspecting methods on standard generic types which use my own types as generic arguments:

  • Tuple<int, string> => works fine
  • Tuple<int, MyType> => exception

I can get the method list from the generic type definition:

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

However, the methods have generic placeholders instead of actual values (like T1, TResult etc.) and I don't feel like writing yet another kludge that traces the generic arguments back to their original values.

A sample of code:

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

So the questions are:

  1. How do I detect if a type is safe to call GetMethods() and similar methods on?
  2. How do I get the actual list of methods and their generic argument values, if the type is not safe?

回答1:


I got an answer in a follow-up question. The TypeBuilder class has a bunch of static overloads which do exactly the thing:

var genericTuple = typeof(Tuple<,>);
var myTuple = genericTuple.MakeGenericType(typeof(int), myType);
var ctor = TypeBuilder.GetConstructor(myTuple, genericTuple.GetConstructors().First());

Strangely, there's no overload of GetProperty. However, property getters and setters can still be resolved using GetMethod:

var genericGetter = typeof(Tuple<,>).GetProperty("Item1").GetMethod;
var actual = TypeBuilder.GetMethod(myTuple, genericGetter);



回答2:


I'll refer you to the documentation:

Defining a Type with Reflection Emit

which says

Although TypeBuilder is derived from Type, some of the abstract methods defined in the Type class are not fully implemented in TypeBuilder. These TypeBuilder methods throw the NotSupportedException. The desired functionality can be obtained by retrieving the created type using Type.GetType or Assembly.GetType and reflecting on the retrieved type.

So:

How do I detect if a type is safe to call GetMethods() and similar methods on?

If the type object is a TypeBuilder, or if the type refers to any type that is a TypeBuilder, then it is not safe to do so.

How do I get the actual list of methods and their generic argument values, if the type is not safe?

I'll refer you to the documentation again. Actually emit the type into an assembly and then get it out of the assembly.



来源:https://stackoverflow.com/questions/15646881/reflection-generated-and-generic-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!