1

情況:我有多個MVC區域,我想在每個獨立工作的區域設置統一IOC(UnityConfig.cs)。在多個MVC區域中使用多個Unity IOC容器

問題:IOC容器會覆蓋自身。

問題:如何讓容器在每個區域都是唯一的? 或如何將RegisterType項目添加到Area中的現有容器(例如在根網站中)?

由於提前,

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

回答

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

的統一集成包可能缺乏UnityControllerFactory,但創建一個將是微不足道的(你可以簡單地從DefaultControllerFactory派生)。

請注意,在一個應用程序中運行隔離模塊配備了額外的開發成本,因此應用程序的大小必須證明它。擁有多個容器實例使您的註冊變得複雜,因此通常最好不要這樣做。