现代分层架构实施

Modern Layered Architecture Implementation

我最近读完了 Dino Esposito 的好书 Modern Web Development,他在书中提出了针对 Web 应用程序的领域驱动分层架构的建议。我一直在努力解决我看到的与以下类似的特定建议:

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

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

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

编辑

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

回答您的问题

从根本上说,你的问题是 "I am looking for is a possible, actual concrete way to implement this pattern without dragging the System.Web.MVC namespace down to the infrastructure layer"

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

IDependencyResolver 不必是系统范围的分辨率接口 - 它只是 MvC 使用的接口。还有其他 IoC 容器,其中一些提供适配器以注入 IDependencyResolver 的实现,包装了它们的 IoC 逻辑。

这允许一些事情:

  1. 依赖执行显式解析能力的MvC组件仍然可以依赖IDependencyResolver
  2. 系统中的其他层可能依赖于不同的分辨率接口,因此包含对隔离的专用程序集的引用
  3. MvC 层和其他层都将访问同一组 dependency/implementation 注册

一些支持此功能的 IoC 容器示例:

  • Autofac - with Autofac Mvc Support

    • 可以看到样本的最后一行是:

      DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
      
    • 在那行之后,任何依赖于 IDependencyResolver 的 MvC 组件将自动获得 AutofacDependencyResolver,它包装了对 Autofac 容器的调用

  • StructureMap - StructureMap.Mvc

这里有一个 comparison of a large number of c# IoC containers 可以帮助您 select 最适合您的那个。

[实际实施问题 - 也就是我对为什么这不是一个好主意的看法]

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

第一个问题 - 为什么?

虽然根据该图,该答案提供了一种方法来完成您的要求,但我承认我不清楚依赖领域层的 IoC 解析器的目的是什么,以及您为什么会这样做需要这样做。

如果您发现自己这样做,您可能不小心使用了 Service Location Anti-Pattern

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

理解意图的部分问题在于图表本身 - 人们经常会通过拖放一些框并将它们连接起来来绘制图表 - 却不清楚线条的含义。它们是依赖链吗?它们是执行顺序吗?从域模型框到基础设施层的实际 label 有一条线是什么意思???是什么都不依赖吗?或者说明此处未阐明的可能依赖关系?

应该使用什么 IoC 解析器?

系统中唯一应该直接引用 IoC 解析器的部分是组合根,它实际上是应用程序的入口点。第一部分 'wires up the object graph' - 实际上,它记录了如何解决从所依赖的接口到适当的具体实现的所有可能的依赖关系。

然后解析入口点对象(或注册一个 IDependencyResolver 以便 Mvc 可以解析入口点对象,也就是控制器)。当入口对象被解析时,它会自动解析它的所有依赖关系,在此过程中解析下一层依赖关系,依此类推,直到到达 类 没有依赖关系。如果你正在做 DDD,这很可能是你的领域层。

无依赖域层和洋葱架构

既然您对 DDD 感兴趣,那么公认的观点是领域层不应依赖于领域层中未定义的任何内容。如果确实需要使用存储库等基础设施组件的服务,则使用分离的接口并将接口放在领域层,但在具体的持久层中实现。

这种架构模式被称为 Onion Architecture also known as the Hexagonal Architecture

使用其他 IoC 容器

虽然我认为没有必要从域层(或任何层)引用 IoC resolver/locator,但我仍然认为采用单独的专用 IoC 容器库是有价值的,如上所述。

价值在于一些关于如何配置服务的更灵活的选项,包括一些基于漂亮约定的自动配置。

可能值得依赖域层中的 IoC 库的一个原因是将 注册和配置逻辑 与正在配置的服务放在一起,这可以帮助构建和组织您的 IoC 依赖项注册。但是仅仅因为您依赖 IoC 程序集来允许构造您的注册,并不意味着您应该使用 IoC resolver/locator.