我正在尝试使用泛型创建一个类型的实例,其中作为泛型传递的类型也具有泛型。
以下代码是出现问题的地方:
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。
我正在尝试做什么,如果是这样,我怎样才能纠正代码以使其有效?
答案 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);