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

时间:2015-04-02 15:43:59

标签: c# generics

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

以下代码是出现问题的地方:

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>>();

这实际上是我尝试做的,但是使用反射,以便可以将参数传递给方法,以便可以创建并返回实例。

但是当我使用反射时,我收到以下错误:

  

无法创建Sapphire.Cms.Web.Routing.RouteTypeWrapper`1 [TRoute]的实例,因为Type.ContainsGenericParameters为true。

我正在尝试做什么,如果是这样,我怎样才能纠正代码以使其有效?

2 个答案:

答案 0 :(得分:1)

MakeGenericType返回一个新类型。它不会修改现有类型。更改您的代码如下,以获得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);
}

答案 1 :(得分:1)

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

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);