具有泛型的类型,其中作为泛型传递的类型也具有泛型导致 ArgumentException

Type with a generic where the type passed as a generic also has a generic causes an ArgumentException

我正在尝试创建具有泛型的类型的实例,其中作为泛型传递的类型也具有泛型。

出现问题的代码如下:

internal virtual RouteBase GetRoute(DbContextTypeProvider databaseContextTypeProvider, Type model)
{
    Type catchallRoute = typeof(CatchallRoute<,>);
    catchallRoute.MakeGenericType(new Type[] {
        databaseContextTypeProvider.DbContextType,
        model
    });

    Type routeTypeWrapper = typeof(RouteTypeWrapper<>);
    routeTypeWrapper.MakeGenericType(new Type[] {
        catchallRoute
    });

    RouteTypeProvider routeTypeProvider = (RouteTypeProvider)Activator.CreateInstance(routeTypeWrapper);

    return GetRoute(databaseContextTypeProvider, model, routeTypeProvider);
}

我的代码基于以下 SO 问题中可以看到的内容,当我以与接受的答案中所示相同的方式使用一种需要泛型的类型时,可以创建实例,但该类型需要一个类型泛型我似乎无法正常工作:

Pass An Instantiated System.Type as a Type Parameter for a Generic Class

我在 MSDN 上找不到任何示例来说明如何使用泛型创建类型的实例,其中它需要的泛型之一也需要泛型。

如果我对其进行编码以便关闭类型,它将如下所示:

RouteTypeWrapper<CatchallRoute<SapphireDbContext<SiteTree>,SiteTree>> routeTypeProvider = new RouteTypeWrapper<CatchallRoute<SapphireDbContext<SiteTree>,SiteTree>>();

这实际上是我正在尝试做的事情,但使用了反射,以便可以将参数传递给方法,从而可以创建和返回实例。

但是当我使用反射时出现以下错误:

Cannot create an instance of Sapphire.Cms.Web.Routing.RouteTypeWrapper`1[TRoute] because Type.ContainsGenericParameters is true.

我正在尝试做的事情是否可行?如果可行,我该如何更正代码以使其正常工作?

MakeGenericType returns 一个新类型。它不会修改现有类型。如下更改代码以获得 MakeGenericType

的结果
internal virtual RouteBase GetRoute(DbContextTypeProvider databaseContextTypeProvider, Type model)
{
    Type catchallRoute = typeof(CatchallRoute<,>).MakeGenericType(new Type[] {
        databaseContextTypeProvider.DbContextType,
        model
    });

    Type routeTypeWrapper = typeof(RouteTypeWrapper<>).MakeGenericType(new Type[] {
        catchallRoute
    });

    RouteTypeProvider routeTypeProvider = (RouteTypeProvider)Activator.CreateInstance(routeTypeWrapper);

    return GetRoute(databaseContextTypeProvider, model, routeTypeProvider);
}

这是一个简单的例子,展示了如何做到这一点。

class A<T>{}
class B<T>{}
class C<T>{}

...

var atype = typeof(A<>).MakeGenericType(new [] { typeof(int) });
var btype = typeof(B<>).MakeGenericType(new [] { atype });
var ctype = typeof(C<>).MakeGenericType(new [] { btype });

var cinstance = Activator.CreateInstance(ctype);