情况:我有多个MVC区域,我想在每个应该独立工作的区域设置统一IOC(UnityConfig.cs)。
问题:IOC容器会覆盖自己。
问题:如何使每个区域的容器独一无二? 或者如何从区域中将RegisterType项添加到现有容器(例如在根网站中)?
提前致谢,
Mogica
区域1
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<DbContext, CmsContext>(new HierarchicalLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterType<ISiteRepository, SiteRepository>();
container.RegisterType<IPageRepository, PageRepository>();
container.RegisterType<IViewRepository, ViewRepository>();
}
区域2
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IPostRepository, PostRepository>();
}
Area3中
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IJobRepository, JobRepository>();
}
答案 0 :(得分:2)
如果您希望通过为每个隔离的部件提供不同的容器实例(通过有效地使每个区域成为模块)来隔离应用程序的部分,则必须拦截控制器的创建并将其分派到正确区域的容器中。
通过实施自定义IControllerFactory
来拦截控制器的创建。这样的实现可能如下所示:
public class PerAreaControllerFactoryComposite : IControllerFactory {
private IDictionary<string, IControllerFactory> areaControllerFactories;
public PerAreaControllerFactoryComposite(
IDictionary<string, IControllerFactory> areaControllerFactories) {
this.areaControllerFactories = areaControllerFactories;
}
public IController CreateController(RequestContext requestContext,
string controllerName) {
var factory = this.FindFactory(requestContext);
var controller = factory.CreateController(requestContext, controllerName);
HttpContext.Current.Items["Factory_" + controller.GetType().Name] = factory;
return controller;
}
public void ReleaseController(IController controller) {
var factory = HttpContext.Current.Items["Factory_" + controller.GetType().Name]
as IControllerFactory;
factory.ReleaseController(controller);
}
public SessionStateBehavior GetControllerSessionBehavior(
RequestContext requestContext, string controllerName) {
var factory = this.FindFactory(requestContext);
return factory.GetControllerSessionBehavior(requestContext, controllerName);
}
private IControllerFactory FindFactory(RequestContext context) {
string area = context.RouteData.DataTokens["area"].ToString();
return this.areaControllerFactories[area];
}
}
此IControllerFactory
实现接受带有IControllerFactory
实现集合的字典,其中字典的键是区域的名称。调用CreateController
时,它将确定当前区域并将调用转发给该区域的IControllerFactory
实施。
您可以按如下方式创建此实现:
var factory = new PerAreaControllerFactoryComposite(new Dictionary
{
{ "Area1", new UnityControllerFactory(area1Container) },
{ "Area2", new UnityControllerFactory(area2Container) },
{ "Area3", new UnityControllerFactory(area3Container) },
});
ControllerBuilder.Current.SetControllerFactory(factory);
Unity集成包可能缺少UnityControllerFactory
,但创建一个将是微不足道的(您可以简单地从DefaultControllerFactory
派生。)
请注意,在一个应用程序中运行隔离的模块会带来额外的开发开销,因此应用程序的大小必须证明其合理性。有多个容器实例使您的注册变得复杂,因此通常最好不要这样做。