在Asp .Net MVC组合根中配置IoC容器的最佳实践

时间:2011-11-08 16:05:35

标签: c# dependency-injection inversion-of-control

我正在构建一个ASP .Net MVC 2应用程序,我想按照Mark Seemann的书“.Net中的依赖注入”中的想法,所以我在Global.asax文件中注册了我的自定义控制器工厂,我正在配置Controller Factory中的容器如下:

public IController CreateController(RequestContext context, Type controllerType)  
{  
   var container = new Container();
   object controller;

   if(controllerType == typeof(MyControllerOne)
   {
      container.Configure(r => r.
         For<IService>().
         Use<ServiceOne>());
   }
   else if(controllerType == typeof(MyControllerTwo)
   {
       container.Configure(r => r.
          For<IService>().
          Use<ServiceTwo>());
   }
   ......

   return container.GetInstance(controllerType) as IController;
}

现在这个代码可以工作(虽然我可能在某个地方犯了错误,因为我是通过内存写的),依赖关系正在被解析,并且正确的控制器每次都使用正确的依赖关系进行实例化,但似乎对于每个请求,容器被配置为解析当时需要的依赖项。所以我的问题是:

  • 这不是多余的吗?
  • 不应该在Global.asax中完成容器的配置,所以只进行一次?如果是这样,怎么办呢?
  • 通过按照我的方式配置容器,对象生命周期将如何受到影响?我的意思是,最终会有应该具有单例生存期的存储库,其他一些应该通过HTTP请求创建一次,因此也是如此。可能会有什么影响?

非常感谢任何评论,想法和/或建议。

顺便说一句,我正在使用的IoC容器是StructureMap,虽然我认为对于这个特定的问题它可能不太相关。

1 个答案:

答案 0 :(得分:4)

确实,根据请求有条件地注册每个控制器是多余的。使用StructureMap,Controller Factory应如下所示:

public class StructureMapControllerFactory : DefaultControllerFactory
{
    private readonly IContainer container;

    public StructureMapControllerFactory(IContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        this.container = container;
    }

    protected override IController GetControllerInstance(
        RequestContext requestContext, Type controllerType)
    {
        return (IController)this.container.GetInstance(controllerType);
    }
}

所有服务都应无条件地在单个容器实例中注册。例如,您可以使用StructureMap注册所有控制器,如下所示:

this.Scan(x =>
{
    x.AssemblyContainingType<HomeController>();
    x.AddAllTypesOf<IController>();
    x.Include(t => typeof(IController).IsAssignableFrom(t));
});

这基本上只是跟随Register Resolve Release pattern