C# 反射 - 递归类型参数的 MakeGenericType

sto*_*ran 2 c# generics reflection

在我项目的某个地方,我需要创建一个具体的泛型类型,将泛型类型定义(带有单个参数)和该参数的类型作为参数。

为此,我编写了一个非常简单的方法:

Type MakeGenericType(Type definition, Type parameter)
{
    return definition.MakeGenericType(parameter);
}
Run Code Online (Sandbox Code Playgroud)

但是,在某些时候,我需要List<List<T>>使用给定的元素 type创建一个类型T。尽管我能够List<List<T>>使用我的方法创建一个类型,但随后尝试从中创建一个具体类型List<List<int>>失败了 - 请参阅下面的代码:

var genericList = MakeGenericType(typeof(List<>), typeof(List<>)); // success

MakeGenericType(genericList, typeof(int)); // exception
Run Code Online (Sandbox Code Playgroud)

mscorlib.dll 中发生类型为“System.InvalidOperationException”的未处理异常

附加信息:System.Collections.Generic.List`1[System.Collections.Generic.List`1[T]] 不是 GenericTypeDefinition。MakeGenericType 只能在 Type.IsGenericTypeDefinition 为 true 的类型上调用。

此外,以下调用甚至不会编译:

MakeGenericType(typeof(List<List<>>), typeof(int));
Run Code Online (Sandbox Code Playgroud)

我已经检查了这个关于IsGenericTypeDefinition和之间差异的问题ContainsGenericParameters。但是,我仍然没有想法,如何处理像genericList.

显然,使用反射我可以构造一个类型对象,这与它无关 - 这对我来说很困惑。

所以问题是,如何从包含泛型类型定义作为参数的泛型创建具体类型?有可能吗?

Iva*_*oev 5

您需要将传递的类型分解为泛型类型定义,并使用以下内容自下而上构建生成的泛型类型:

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;
}
Run Code Online (Sandbox Code Playgroud)