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

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

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关于IsGenericTypeDefinitionContainsGenericParameters之间的区别。但是,我仍然不知道如何处理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;
}

09-10 03:31
查看更多