假设我有这样一个通用类
public class XClass<T, U>
{
public void MethodA<V>(){}
}
我怎样才能得到
的类型XClass<int,>
不是硬编码,不限于MakeGenericType方法,如下所示。
------使用MakeGenericType ------
进行详细阐述我可以获得未绑定和开放类的类型“XClass&lt;,&gt;”和它的开放方法:
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 <int, char>
及其密切方法:
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<int,char>: \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<String>:\t generic? {0} \t open? {1}"
, fullMethod.IsGenericMethod, fullMethod.IsGenericMethodDefinition));
现在,我如何获得绑定但开放类的类型
XClass<int, >
及其方法?
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,则ArgumentNullException异常将抛出“Value not not null”。
我该怎么办?
答案 0 :(得分:3)
你提出的建议是不可能的,也不会对你有所帮助。
The documentation陈述(强调我的)
使用MakeGenericType构造的类型可以是打开的,也就是说,某些类型 它们的类型参数可以是封闭泛型的类型参数 方法或类型。
这意味着您无法创建代表Type
的{{1}}对象。您可以做的是:
XClass<int,>
在这种情况下,您可以创建一个代表class Outer<TOuter>
{
class XClass<T, U> {}
}
的{{1}}对象。但是需要有一个封闭的泛型类。
文档还指出(参考上面的类似示例):
Base等构造类型在发出代码时很有用, 但是你不能在这种类型上调用MakeGenericType方法,因为它 不是泛型类型定义。创建闭合构造类型 可以实例化,首先调用GetGenericTypeDefinition 获取表示泛型类型定义的Type对象的方法 然后使用所需的类型参数调用MakeGenericType。
这意味着如果你有
Type
然后要为Outer<TOuter>.XClass<int, TOuter>
获取Type myType = ... // represents Outer<TOuter>.XClass<int, TOuter>
,您首先需要致电Type
(从而丢失XClass<int, string>
信息),然后致电myType.GetGenericTypeDefinition()
它返回(以及int
类型参数)。所以这就像退后一步,前进了两步。
您可能需要考虑将MakeGenericType
的类型参数类型存储在单独的数据结构中(例如string
),只要您不知道所有类型参数,然后创建在收集完所有类型之后,一次性关闭泛型类型。
为方便起见,您还可以将所有这些打包成一个小帮助类:
XClass
答案 1 :(得分:2)
不,这是不可能的。
请参阅我的类似问题:Does .Net support curried generics?
答案 2 :(得分:1)
当您使用自己的通用参数提供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);
这将使用openConstructedType
Type
填充XClass<int,U>
。
请注意,该类型将具有ContainsGenericParameters
,因此它不可构造,并且无法填充打开的参数。
答案 3 :(得分:0)
我认为如果没有继承课程,这是可能的。
你似乎要尝试的是基本上通过反思来做到这一点:
typeof(XClass<int,>)
这将是半封闭的...并且只能通过继承AFAIK来实现:
class XClassInt<U>: XClass<int, U> {}
这第二段代码可让您获得typeof(XClassInt<>).BaseType
这就是您想要的。但是,在这种情况下,XClass<,>
的第二个类型参数不是null
,而是U
(来自XClassInt<>
的类型参数)。
另见this MSDN页。
修改:这是我的测试平台:
public class C1<A,B> {}
public class C2<B>: C1<int, B> {}
[...]
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
但是,正如我所说,我认为这是可能的,因为基类型是使用开放泛型类型C2
的泛型类型参数关闭的。