【发布时间】:2020-04-02 14:14:04
【问题描述】:
我正在尝试在使用 EntityFramework 作为 ORM 的 .NET Core 3.1 Web API 项目中实现洋葱架构。
由于我刚刚学习洋葱架构,我对如何在某些领域遵循它的规则有一点问题。其中之一是依赖注入。
假设我们有以下环(从外到内):
- 基础架构(API、持久性)
- 应用程序(服务)
- 域(模型 + 域服务)
根据我对洋葱架构的理解,同一层中的不同关注点不应相互依赖。因此,在基础设施环中,更具体地说,在 API 项目中,我了解如何为我的服务连接 DI,因为这些服务(接口和实现)位于较低的环中。但是,我还需要为我的 DbContext 设置 DI,它在同一个环的 Persistence 项目中定义。此外,同样存在于同一个环中的其他第三方工具也需要通过 DI 连接。
对此我有两种解决方案:
- 使 API 项目依赖于 Persistence 项目(以及其他第三方项目)。据我了解,这违反了洋葱架构规则。
- 将基础架构环分成两个环,其中下半部分将包含 Web API、持久性和任何其他项目,但上半部分将是专用的 DI 层,它将设置所有 DI。我相信这个外层称为组合根。
用另一种方式总结我的问题:在洋葱架构中,如果您使用 DI,那么 DI 看起来应该在基础架构环中,并且看起来 DI 需要引用基础架构环中的所有内容. DI 是否必须作为洋葱架构中的异常处理?如何处理?
【问题讨论】:
-
请注意,不同的服务和层不必映射到单独的项目。并且该项目引用本身不会创建您试图避免的那种依赖关系。
-
@DavidBrowne-Microsoft:对于您的第一点,我同意。然而在我看来,如果代码/项目结构反映(或半反映)架构,它有助于提高可读性,并且对于新加入的人来说,它有助于他们了解事情应该去哪里。对于您的第二点,我有点困惑,因为如果 A 引用 B,那么人们可以使用 A 中 B 中的任何内容。我认为您的意思是引用项目不会创建直接依赖关系?你能详细说明你的意思吗?
-
您可以通过代码审查以外的任何方式实施架构是一种幻想。即使您的代码没有直接使用被引用项目中的类型,直接引用项目进行编译或部署也可能很方便,有时甚至是必要的。
-
一个常见的例子是您的主项目注册服务。最简单的解决方案是让主项目引用每个服务实现的类型。 EG
services.AddScoped<ICustomerRepository, MySQLServerCustomerRepository>();,如果不引用包含存储库实现的程序集,则无法编译该代码。 -
我认为你走极端了 :) 当然我知道我无法“强制执行”它,但为什么不根据架构从逻辑上构建项目呢?我们确实添加了诸如“.Data”或“.Services”之类的后缀,对吗?
标签: c# .net-core dependency-injection architecture onion-architecture