C# .NET内核洋葱架构中的依赖项注入
我试图在一个.NETCore3.1WebAPI项目中实现onion体系结构,该项目使用EntityFramework作为ORM 因为我只是在学习洋葱架构,所以对于如何在某些领域遵循它的规则,我有一个小问题。其中之一是依赖注入 假设我们有以下环(从外到内):C# .NET内核洋葱架构中的依赖项注入,c#,.net-core,dependency-injection,architecture,onion-architecture,C#,.net Core,Dependency Injection,Architecture,Onion Architecture,我试图在一个.NETCore3.1WebAPI项目中实现onion体系结构,该项目使用EntityFramework作为ORM 因为我只是在学习洋葱架构,所以对于如何在某些领域遵循它的规则,我有一个小问题。其中之一是依赖注入 假设我们有以下环(从外到内): 基础架构(API、持久性) 应用程序(服务) 域(模型+域服务) 根据我在洋葱架构中的理解,同一层中的独立关注点不应该相互依赖。因此,在基础设施环中,更具体地说,在API项目中,我了解如何为我的服务连接DI,因为这些服务(接口和实现)位于
- 基础架构(API、持久性)
- 应用程序(服务)
- 域(模型+域服务)
用另一种方式总结我的问题:在洋葱架构中,如果您使用DI,DI看起来应该位于基础设施环中,并且DI需要引用基础设施环中的所有内容。在洋葱架构中,DI是否必须作为异常处理?如何处理这个问题?以下是我的理解: 编译时,域不依赖于自身以外的任何东西。因此,例如,域将不依赖于持久性项目。它将依赖于域本身中定义的抽象 您的持久性(例如,具体的存储库)将满足域中定义的依赖关系。在现实世界中,这通常意味着他们将实现在域中定义的接口 组合根然后配置应用程序,以便具体实现与域中定义的抽象相匹配。这就是DI配置 这是最简单的版本。如果需要的话,你可以增加更多的复杂性。唯一不变的部分是域是自包含的。如果需要的话,这里还有一些增加复杂性的其他方法:
- 依赖项的实现也可以是自包含的,就像域一样。还有一个项目使它们适应域接口。因此,您的存储库不会直接实现域接口
- 域抽象的配置——将它们映射到它们的具体依赖项——可以分开。换句话说,容器设置可以与应用程序主机分离。理想情况下,应用程序主机仍将负责读取其配置或环境值,并将它们传递给该容器配置。这样可以防止容器配置与JSON或.config文件等细节耦合。它更容易测试
您的API可以依赖于持久性项目。您的API不是域。您的API启动将依赖于域和持久性,并配置DI容器来提供持久性项目中的类,以满足域中定义的依赖关系 API类似于域的反面。域不依赖于自身之外的任何东西。其他依赖项指向内部。例如,存储库实现由域定义的抽象 另一方面,API最终取决于一切。它使用DI配置向域提供依赖项(如持久性),这意味着它将依赖于所有依赖项
以下是(在我看来)思想上最大的变化: 我们倾向于为数据访问编写具体的类,调用外部API,以及做其他与域无关的事情。然后我们把接口放在它们上面。这些接口通常看起来像是事后诸葛亮。就像我们只是在创建镜像这些类的接口。如果我们向类中添加了一些内容,我们就会将其添加到接口中 然后我们获取这些接口并开始将它们注入到我们的域中。这就是事情变得一团糟的地方。这些接口与我们的域无关。它们只是存在于域之外的类的镜像。这使得域更难测试。违反了接口隔离。我们发现自己在模仿与我们的领域无关的部分接口 如果我们从依赖于抽象的域类的角度来设计抽象,所有这些都会消失。例如,如果我们的域类需要从存储库中检索数据,那么我们将定义一个存储库,该存储库将精确地建模该域类所需的内容—不多也不少。我们不会采用一些通用的多用途存储库接口并将其塞进我们的域中 我们可能仍然有一些通用的通用存储库。没关系。但我们将其调整为该域存储库接口。域名不知道这件事。它只知道域中定义的抽象。域类依赖于它为自己的目的定义的小型、分离的抽象。