现代分层架构实施

时间:2016-08-26 16:20:28

标签: c# asp.net-mvc domain-driven-design inversion-of-control

我最近读完了Dino Esposito的好书Modern Web Development,并在其中提出了针对Web应用程序的域驱动分层架构的建议。我一直在努力处理我看到的类似于以下建议的具体建议: enter image description here

具体参考基础设施层中的IoC。我理解这背后的原因并且对我有意义但是你如何在ASP.NET MVC框架的范围内充分实现它?要添加依赖项解析程序,您需要实现System.Web.MVC名称空间中存在的IDependencyResolver接口。

在过去的项目中,我通常会在启动文件夹中的MVC应用程序中实现我的IoC,但这似乎与布局的建议不一致。

我不想把它变成一个意见类型的问题,我正在寻找的是一种可能的,实际的具体方法来实现这种模式,而无需将System.Web.MVC命名空间拖到基础架构层。

修改

要为建议的体系结构添加后续图表,以及仍然让我感到困惑的部分,看起来Dino的建议确实将IoC容器放在基础架构组件中:

Boxes are assemblies

1 个答案:

答案 0 :(得分:3)

回答您的问题

从根本上说,你的问题是"我正在寻找一种可能的,实际的具体方法来实现这种模式,而无需将System.Web.MVC命名空间拖到基础设施层"

有一种方法可以做到这一点,它涉及引入一个专门用于此目的的新IoC容器库。

IDependencyResolver不一定是你的系统广泛分辨率接口 - 它只是MvC使用的接口。还有其他IoC容器,其中一些容器提供适配器来注入包装其IoC逻辑的IDependencyResolver实现。

这允许一些事情:

  1. 依赖于执行显式解析的能力的MvC组件仍然可以依赖于IDependencyResolver
  2. 系统中的其他层可能依赖于不同的分辨率界面,因此包含对隔离的适合目的组件的引用
  3. MvC层和其他层都将访问同一组依赖/实现注册
  4. 支持此功能的IoC容器的一些示例:

    • Autofac - Autofac Mvc Support

      • 您可以看到示例的最后一行是:

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        
      • 在该行之后,依赖IDependencyResolver的任何MvC组件将自动获取包含对Autofac容器的调用的AutofacDependencyResolver

    • StructureMap - StructureMap.Mvc

    这是一个comparison of a large number of c# IoC containers,可以帮助您选择适合您的那个。

    [实际执行问题 - 也就是为什么这不是一个好主意我的观点]

    在我看来,您过去在Mvc应用程序中仅使用IoC的项目更为正确,因此您可能已经熟悉以下概念,但是当您考虑从域中引用IoC时,我认为值得探索。

    第一个问题 - 为什么?

    虽然这个答案提供了一种方法,可以根据该图表进行您所要求的操作,但我承认,根据域层的IoC解析器,我的目的不明确,以及为什么你需要这样做。

    如果您发现自己这样做,可能会意外使用Service Location Anti-Pattern

    如该博客所述,没有必要依赖于IoC解析器(或定位器) - 只需依赖于您需要的服务,并让IoC注入适当的实现。

    理解意图的部分问题在于图表本身 - 通常情况下,人们通过放下一些框并连接它们来绘制图表 - 而不必清楚线条的含义。他们是依赖链吗?它们是执行顺序吗?从域模型框到基础设施层的实际标签有一条线是什么意思?这取决于什么?或说明这里没有明确表达的可能依赖性?

    IoC解析器应该使用什么?

    系统中唯一应该直接引用IoC解析器的部分是组合根,它实际上是应用程序的入口点。第一部分连接对象图表' - 实际上,它注册了如何从依赖的接口解决所有可能的依赖关系,以及适当的具体实现。

    然后解析入口点对象(或注册IDependencyResolver,以便Mvc可以解析入口点对象,也就是控制器)。解析条目对象后,它会自动解析所有依赖关系,在解析下一层依赖关系的过程中,依此类推,直到您到达没有依赖关系的类。如果您正在使用DDD,那么这可能是您的域层。

    无依赖关系的域层和洋葱架构

    由于您对DDD感兴趣,因此接收的智慧是域层不应该依赖于域层中未定义的任何内容。如果确实需要利用基础架构组件(如存储库)的服务,请使用单独的接口并将接口放在域层中,但将实现放在具体的持久层中。

    这适用的架构模式称为Onion Architecture,也称为Hexagonal Architecture

    使用其他IoC容器

    虽然我认为有必要从域层(或任何层,实际上)引用IoC解析器/定位器,但我仍然认为采用单独的专用IoC容器是有价值的图书馆,如上所述。

    该值是一些更灵活的选项,用于配置服务,包括一些基于nifty约定的自动配置。

    依赖于域层中的IoC库可能值得的一个原因是将注册和配置逻辑与正在配置的服务共同定位,这有助于构建和组织您的IoC依赖注册。但仅仅因为您依赖IoC程序集来允许构建注册,并不意味着您应该使用IoC解析器/定位器。