洋葱架构是否与IoC相矛盾?

时间:2013-02-28 11:35:47

标签: inversion-of-control onion-architecture

Jeffrey Palermo是洋葱建筑的先驱,我找到了一个很好的方法。

http://www.headspring.com/jeffrey/onion-architecture-part-4-after-four-years/

然而他的声明“内层定义接口。外层实现接口”似乎与IoC相矛盾,如果我的理解是正确的,它表明Consumer定义接口和提供者实现它,即控制在于消费者而不是提供者。

这个原则对我来说很有意义,因为,想象一下你正在编写一个用户界面,这个原则意味着你可以继续创建你的用户界面,而不需要知道你将要调用的服务,因为你负责定义界面这暴露了你需要的所有功能。

所以为此,Jeffreys的声明似乎是一个矛盾,让我对合同(界面定义)的位置感到困惑,因为它似乎意味着:     域层         myEntity所         IMyService     服务         MyEntityService:IMyService

由于Domain下面没有图层,我在哪里放置IMyEntity。这也意味着我不能创建一个Presentation项目,直到Domain存在并定义了IMyService。

正如我所说,我在哪里放置IMyEntityRepository和MyEntityRepository?由于服务依赖于IMyEntityRepository而MyEntityRepository依赖于IMyEntity

4 个答案:

答案 0 :(得分:5)

那么,从哪里开始? : - )

让我们从IOC的真正角色开始。根据{{​​3}},

  

Inversion Of Control是一种编程技术,其中包含对象   耦合在运行时由汇编程序对象绑定,通常是   在编译时不知道。

在您的情况下,您的UI将在不知道将在运行时绑定的服务实现的情况下操作服务接口。定义这些服务接口并不取决于消费者;它们将在您的Onion架构的应用程序核心中定义,但我们稍后会看到它。

“内层定义接口。外层实现接口”,这就是洋葱架构的设计方式,但不要忘记最外层是IOC!由IOC在运行时将接口与正确的实现绑定在一起!

你是对的,如果没有至少一个可用于你将操作的接口的实现,你的UI将无法工作。但在这种情况下,如果出于任何原因需要首先构建UI,请考虑使用模拟框架!

您的上一个问题是您需要放置IMyEntityRepository和MyEntityRepository类的位置。嗯,这是最简单的部分;-) IMyEntityRepository肯定需要放在你的应用程序核心中。您的所有实体,服务接口,存储库接口和任何接口都需要位于同一位置。 MyEntityRepository实现应放在您的基础架构层中的某个位置,因为他的角色主要是处理从数据库中获取数据。

希望有所帮助!

答案 1 :(得分:4)

我与Jeffrey合作多年,我想说IoC是使Onion Architecture成为可能的不可或缺的组成部分。外部依赖关系的接口在具有很少(如果有)依赖关系的项目中定义(换句话说,洋葱的“中心”项目)。实现依赖于外部依赖性的那些接口的类位于洋葱边缘/表面上的项目中。因此,需要IoC容器在运行时将洋葱边缘的类实现“连接”到洋葱核心的接口。

答案 2 :(得分:2)

我们已经在我的项目上实现了Onion,这在概念上非常简单。

  1. 创建一个只包含接口和POCO的项目,我们现在称之为合同
  2. 创建一个或多个包含接口实现的项目以及所有第三方的东西,如NHibernate映射,我们称之为实现
  3. 从需要使用此功能的项目添加对Contract的直接引用,但不从这些项目添加对Implementation的引用
  4. 在您的复合根(应用程序入口点)项目中做两件事(1)作为构建的一部分将最新版本的实现复制到配置的位置(我们使用AppSettings进行配置,但这里有很多选项) (2)让您的容器扫描您的Implementation Dll的配置位置
  5. 这种方法允许您只依赖Contract,并且您可以切换实现,因此如果您希望将来迁移到Entity Framework或其他内容,您只需使用该框架重新实现实现。

    我们还将NHibernate DLL复制到配置的扫描位置,这样我们就可以使架构变得防御,因此很难不遵循它,因为NHibernate仅在应该使用的地方可用。

答案 3 :(得分:0)

洋葱架构中的接口是层依赖(即消耗)的接口,其实现确实由提供由外层。

更具体地说,架构本身并没有说你必须抽象接口背后的业务逻辑(关于dependency inversion principle你可能应该做什么,但这是另一个故事)。所说的是层的依赖关系应该建模为接口,因此实现可以由外层提供。

最好的例子是基础设施代码,尤其是数据访问。您的业​​务逻辑需要加载和存储数据,因此它定义了一个消费的接口。外层将使用NHibernate或EF或其他任何方式提供实现。

实际上,低级别图层(来自DIP;即数据访问和其他商品)位于洋葱的最外层,而高级图层(即业务逻辑)离中心更近。

另请参阅http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html,用实体替换业务逻辑更多业务逻辑条款用例接口适配器哪些IMO更容易推理。您离中心越远,您对用户看到和使用的内容就越具体;离中心越近越通用;在中心是那些横向于您的企业的东西,然后特定于您的应用程序的用例更多地没有规定它们将如何被使用或在哪个环境(哪个DB,哪个UI等),然后你将在你的用例和技术框架之间建立适配器(ASP.NET MVC,WCF,WPF-在非网络场景中,EF,NHibernate等)。