在我项目的某个地方,我需要制作一个具体的泛型类型,将泛型类型定义(带有单个参数)和该参数的类型作为参数。
为此,我编写了一个非常简单的方法:
Type MakeGenericType(Type definition, Type parameter)
{
return definition.MakeGenericType(parameter);
}
但是,在某些时候,我需要使用给定的元素类型
List<List<T>>
创建一个类型,例如T
。尽管我可以使用自己的方法创建类型List<List<T>>
,但随后尝试从中创建具体类型List<List<int>>
的尝试失败-请参见以下代码:var genericList = MakeGenericType(typeof(List<>), typeof(List<>)); // success
MakeGenericType(genericList, typeof(int)); // exception
类型为“ System.InvalidOperationException”的未处理异常
发生在mscorlib.dll中
附加信息:
System.Collections.Generic.List`1 [System.Collections.Generic.List`1 [T]]
不是GenericTypeDefinition。 MakeGenericType只能在
Type.IsGenericTypeDefinition为true的类型。
而且,以下调用甚至不会编译:
MakeGenericType(typeof(List<List<>>), typeof(int));
我已经检查过this question关于
IsGenericTypeDefinition
和ContainsGenericParameters
之间的区别。但是,我仍然不知道如何处理genericList
这样的类型对象。显然,使用反射我可以构造一个类型对象,这与它无关,这使我非常困惑。
所以问题是,如何从包含泛型类型定义作为参数的泛型中创建具体类型?有可能吗?
最佳答案
您需要将传递的类型分解为通用类型定义,并使用类似以下的方法自底向上构建最终的通用类型:
static Type MakeGenericType(Type definition, Type parameter)
{
var definitionStack = new Stack<Type>();
var type = definition;
while (!type.IsGenericTypeDefinition)
{
definitionStack.Push(type.GetGenericTypeDefinition());
type = type.GetGenericArguments()[0];
}
type = type.MakeGenericType(parameter);
while (definitionStack.Count > 0)
type = definitionStack.Pop().MakeGenericType(type);
return type;
}