C#语言:如何获取绑定但开放的Generic类的类型?
假设我有这样一个通用类
public class XClass { public void MethodA(){} }
我怎么能得到这种类型的
XClass
没有硬编码,不限制MakeGenericType方法,如下所示。
——使用MakeGenericType ——详细阐述
我可以得到未绑定和开放类“XClass ”的类型及其open方法:
var type = typeof(XClass); Console.WriteLine(String.Format("Type ZClass: \t generic? {0} \t open? {1}" , type.IsGenericType, type.IsGenericTypeDefinition)); var method = type.GetMethod("MethodA"); Console.WriteLine(String.Format("Method MethodA: \t generic? {0} \t open? {1}" , method.IsGenericMethod, method.IsGenericMethodDefinition));
另外,我可以得到全封闭类的类型
XClass
及其密切方法:
var type = typeof(XClass); var method = type.GetMethod("MethodA"); var fullType = method.DeclaringType.MakeGenericType(new[]{typeof(int), typeof(char)}); Console.WriteLine(String.Format("Type ZClass: \t generic? {0} \t open? {1}" , fullType.IsGenericType, fullType.IsGenericTypeDefinition)); var fullTypeOpenMethod = fullType.GetMethod("MethodA"); var fullMethod = fullTypeOpenMethod.MakeGenericMethod(typeof(string)); Console.WriteLine(String.Format("Method MethodA:\t generic? {0} \t open? {1}" , fullMethod.IsGenericMethod, fullMethod.IsGenericMethodDefinition));
现在,我怎样才能获得绑定但开放类的类型
XClass
和它的方法?
var type = typeof(XClass); var method = type.GetMethod("MethodA"); Type [] types = new Type[2]; types[0] = typeof(int); types[1] = null; // what shall i put here? var halffullType = method.DeclaringType.MakeGenericType(types);
如果我将types [1]设置为null,则ArgumentNullExceptionexception将抛出“Value not not null”。
我该怎么办?
你提议做什么是不可能的,也不会真正帮助你。
因为…不可能
文件说明(强调我的)
使用MakeGenericType构造的类型可以是开放的,也就是说,它们的一些类型参数可以是封闭generics方法或类型的类型参数 。
这意味着您无法创建表示XClass
的Type
对象。 你能做的是:
class Outer { class XClass {} }
在这种情况下,您可以创建一个Type
对象,表示Outer
。 但是需要有一个封闭的generics类。
没用,因为……
文档还指出(参考上面的类似示例):
在发出代码时,诸如Base之类的构造类型很有用,但是您不能在此类型上调用MakeGenericType方法,因为它不是generics类型定义。 要创建可以实例化的闭合构造类型,首先调用GetGenericTypeDefinition方法以获取表示generics类型定义的Type对象,然后使用所需的类型参数调用MakeGenericType。
这意味着,如果你有
Type myType = ... // represents Outer.XClass
然后要获取XClass
的Type
,首先需要调用myType.GetGenericTypeDefinition()
(从而丢失int
信息),然后调用MakeGenericType
将其重新放入(以及string
类型参数)。 所以这就像退后一步,前进了两步。
备择方案
您可能需要考虑将XClass
的类型参数类型存储在单独的数据结构中(例如, Type[]
),只要您不知道所有类型参数,然后在您拥有之后一次创建封闭的generics类型收集了所有这些。
为方便起见,您还可以将所有这些打包成一个小帮助程序类:
class GenericTypeDescription { private readonly Type openGenericType; private readonly Type[] typeParameters; public GenericTypeDescription(Type openGenericType) { // add checks for openGenericType actually being what it says here this.openGenericType = openGenericType; this.typeParameters = new Type[openGenericType.GetGenericArguments().Length]; } public void SetTypeParameter(int index, Type type) { // add error handling to taste this.typeParameters[index] = type; } public Type ConstructGenericType() { // add error handling to taste return this.openGenericType.MakeGenericType(this.typeParameters); } }
不,这是不可能的。
看到我的类似问题: .Net是否支持curried的generics?
当您使用自己的通用参数提供MakeGenericType时,这是可能的。
var type = typeof(XClass<,>); var method = type.GetMethod("MethodA"); Type[] types = new Type[2]; types[0] = typeof(int); types[1] = type.GetGenericArguments()[1]; // Use the open parameter type var openConstructedType = type.MakeGenericType(types);
这将使用Type
of XClass
填充openConstructedType
。
请注意,该类型将具有ContainsGenericParameters
,因此它不可构造,并且无法填充打开的参数。
我不认为没有inheritance课程就可以做到这一点。
你似乎要尝试的是通过reflection基本上做到这一点:
typeof(XClass)
这将是半封闭的…并且只能通过inheritanceAFAIK来实现:
class XClassInt: XClass {}
第二个代码允许你获得typeof(XClassInt<>).BaseType
是你想要的。 但是,在这种情况下, XClass<,>
的第二个类型参数不是null
而是实际上是U
(来自XClassInt<>
的类型参数)。
另请参阅此MSDN页面。
编辑:这是我的测试平台:
public class C1 {} public class C2: C1 {} [...] Type baseType = typeof(C2<>).BaseType; WL(baseType); WL(baseType.GetGenericArguments()[0]); Type arg1 = baseType.GetGenericArguments()[1]; WL(arg1); WL(arg1.DeclaringType); WL(arg1.GenericParameterPosition); WL(arg1.IsGenericParameter);
运行此产生:
C1`2[System.Int32,B] System.Int32 B C2`1[B] 0 True
但是,正如我所说,我认为这是唯一可能的,因为基类型是使用开放generics类型C2
的generics类型参数关闭的。