2014-11-04 110 views
0

我有一个MVC应用程序,我正在使用Autofac解决依赖关系。Autofac注册多个容器

我有一种情况,我必须创建2个容器,运行时应根据条件决定使用哪个容器。

条件是如果控制器Home被调用,我需要使用container1,否则我必须使用container2。

Application_Start是我注册容器的地方。

我不知道如何在运行时发生这种情况。任何帮助,高度赞赏。

感谢来自不同的容器,让控制器决心

+0

容器之间有多少注册不同?有一个委托工厂或其他一些方式来改变运行时实例化可能更有意义 – ESG 2014-11-04 01:25:19

+0

一些注册有所不同,如果你可以帮我解决一些代码示例的问题,那将是非常好的。 – user2388339 2014-11-04 01:40:02

+0

我建议查看Autofac文档的[选择实施者](https://github.com/autofac/Autofac/wiki/Component-Creation)部分。您还应该更好地解释您首先要做的事情,而不是询问具体实施的细节。 – ESG 2014-11-04 01:55:35

回答

1

的一个原因是,如果你的应用程序由多个独立的模块。在这种情况下,您可能不希望模块互相影响,并且每个模块都有一个容器是合理的。然而,在几乎所有其他情况下,拥有多个容器实例都没有意义。

所以,如果你需要这个,你需要建立自己的定制IControllerFactory,可以根据控制器类型切换容器。举例来说,这样的事情:

internal sealed class MultiplContainerControllerFactory : IControllerFactory 
{ 
    public IController CreateController(RequestContext requestContext, string controllerName) 
    { 
     var factory = this.GetFactory(requestContext); 
     var controller = factory.CreateController(requestContext, controllerName); 

     // By storing the factory in the request items for this controller, 
     // we allow it to be easily retrieved 
     // during ReleaseController and delegate releasing to the correct controller. 
     HttpContext.Current.Items["ContrFct_" + controller.GetType().FullName] = factory; 

     return controller; 
    } 

    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, 
     string controllerName) 
    { 
     var factory = this.GetFactory(requestContext); 
     return factory.GetControllerSessionBehavior(requestContext, controllerName); 
    } 

    public void ReleaseController(IController controller) 
    { 
     var controllerFactory = (IControllerFactory)HttpContext.Current.Items["ContrFct_" + 
      controller.GetType().FullName]; 

     controllerFactory.ReleaseController(controller); 
    } 

    private IControllerFactory GetFactory(RequestContext context) 
    { 
     // return the module specific factory based on the requestcontext 
    } 
} 

除此之外,您将需要有每个集装箱特殊AutofacControllerFactory。这可能看起来像这样:

public sealed class AutofacControllerFactory : DefaultControllerFactory 
{ 
    public readonly IContainer Container; 
    private readonly string moduleName; 

    public AutofacControllerFactory(IContainer container, string moduleName) 
    { 
     this.Container = container; 
     this.moduleName = moduleName; 
    } 

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      // The base method throws an expressive 404 HTTP error. 
      base.GetControllerInstance(requestContext, controllerType); 
     } 

     // We need to start a new lifetime scope when resolving a controller. 
     // NOTE: We can apply MatchingScopeLifetimeTags.RequestLifetimeScopeTag to the BeginLifetimeScope 
     // method and in this case we can use .InstancePerRequest(), but in that case it becomes impossible to 
     // verify the DI configuration in an integration test. 
     ILifetimeScope lifetimeScope = this.Container.BeginLifetimeScope(); 

     // We need to store this lifetime scope during the request to allow to retrieve it when the controller 
     // is released and to allow to dispose the scope. Memory leaks will be ensured if we don't do this. 
     HttpContext.Current.Items[controllerType.FullName + "_lifetimeScope"] = lifetimeScope; 

     // This call will throw an exception when we start making registrations with .InstancePerRequest, 
     // because the WebRequest functionality of Autofac is tied to the AutofacDependencyResolver, which we 
     // don't use here. We can't use the AutofacDependencyResolver here, since it stores the created lifetime 
     // scope in the HttpContext.Items, but it uses a fixed key, which means that if we resolve multiple 
     // controllers for different application modules, they will all reuse the same lifetime scope, while 
     // this scope originates from a single container. 
     try 
     { 
      return (IController)lifetimeScope.Resolve(controllerType); 
     } 
     catch (Exception ex) 
     { 
      lifetimeScope.Dispose(); 

      throw new InvalidOperationException("The container of module '" + this.moduleName + 
       "' failed to resolve controller " + controllerType.FullName + ". " + ex.Message, ex); 
     } 
    } 

    [DebuggerStepThrough] 
    public override void ReleaseController(IController controller) 
    { 
     try 
     { 
      base.ReleaseController(controller); 
     } 
     finally 
     { 
      var scope = (ILifetimeScope)HttpContext.Current 
       .Items[controller.GetType().FullName + "_lifetimeScope"]; 

      scope.Dispose(); 
     } 
    } 
}