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方法或类型的类型参数

这意味着您无法创建表示XClassType对象。 你能做的是:

 class Outer { class XClass {} } 

在这种情况下,您可以创建一个Type对象,表示Outer.XClass 。 但是需要有一个封闭的generics类。

没用,因为……

文档还指出(参考上面的类似示例):

在发出代码时,诸如Base之类的构造类型很有用,但是您不能在此类型上调用MakeGenericType方法,因为它不是generics类型定义。 要创建可以实例化的闭合构造类型,首先调用GetGenericTypeDefinition方法以获取表示generics类型定义的Type对象,然后使用所需的类型参数调用MakeGenericType。

这意味着,如果你有

 Type myType = ... // represents Outer.XClass 

然后要获取XClassType ,首先需要调用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类型参数关闭的。