1

我了解 IoC 的基本概念,但我很难将我的视野扩展到最初的概念之外。


基本上,使用 DI 框架,我不应该再对具有依赖关系的对象使用 new 关键字,因为那时我没有调用 DI 框架解析方法,因此不会触发解析链。

用户想要一个对象A,他需要一个对象B,他想要一个对象C,他想要......

这就是使用 DI 框架会发生的事情。但是使用 new 关键字,我会得到:

我只是实例化一个对象 A

问题1:我说得对吗?错误的 ?还是又是“取决于”的情况?


我刚刚阅读了 Mark Seemann 的回答(https://stackoverflow.com/a/2490797/2671072),他说:

DI Container 应该在应用程序的 Composition Root 中解析整个依赖关系图并让开。

问题 2:他是否暗示应该调用 DI 框架(以解决某些问题)的唯一时间是从应用程序的开始,并且从那里开始,一切都应该没问题,不理会?


我正在做一个项目。但是我很难定义接口和类(实体、值对象、实现)应该去哪里(程序集、命名空间命名......)。

问题 3:DI 是否意味着代码组织的特殊结构?


我听说领域/业务层不应该引用任何 DI 框架。

问题 4:该建议是否也适用于任何其他层?还是假的?


我正在使用两个库(比如 LibraryA 和 LibraryB)。LibraryB 包含三个类,ClassA、ClassB、ClassC。每个类都依赖于前一个(ClassA 是根/聚合)。LibraryA 依赖于 ClassA。

问题5:是在LibraryB内部创建一个工厂,专门创建ClassA及其依赖(只使用new关键字),还是充分利用DI框架,手动注册ClassA,ClassB,ClassC,并解决 ClassA ?

4

2 回答 2

4

我不应该再使用 new 关键字

这完全是关于newables 和 injectionables 之间的差异。是的,您绝对应该使用 new 关键字,但不适用于服务/注射剂。

他是否暗示应该调用 DI 框架(以解决某些问题)的唯一时间是从应用程序的开始

您需要为每个请求解决一次。如果您的应用程序处理单个请求并死掉(例如控制台应用程序),这意味着您在启动期间解决了一次。然而,大多数应用程序类型(Web 应用程序、Web 服务、桌面应用程序等)处理许多请求(有时是并发的),这意味着将解析许多“根”对象。

对每个请求进行解析(无论“请求”可能在该应用程序的上下文中)很重要,因为对整个应用程序域进行一次解析将创建一个对象图,这意味着该对象图应该是线程安全的并且可重复使用。您也许可以使这项工作正常进行,但这通常需要大量工作并且容易出错。这就是为什么 DI 容器通常包含在特定范围内注册服务的复杂方法(每个 Web 请求、每个 WCF 操作等)。

DI 是否意味着代码组织的特殊结构?

不,不是的。DI 不会强迫您进入某种组织结构,但您必须使用松散耦合SOLID设计类才能获得最大收益

我听说领域/业务层不应该引用任何 DI 框架。该建议是否也适用于任何其他层?还是假的?

是的,这个建议适用于系统的每个部分,除了您的Composition Root。但请注意,一个层不等于一个程序集。看看这个问题及其答案

在 LibraryB 中创建工厂是否更好

如果没有更多信息,这很难回答(您可能想为此提出一个新问题),但通常您应该只为每个请求解析一个对象,并让容器构建整个图表。如果LibraryA 使用LibraryB 中的ClassA,那么LibraryA 中将有一个或多个类依赖于ClassA。因此,与其直接从容器中解析 ClassA,不如从容器中解析 LibraryA 的类之一——或者递归地解析它们的父类之一。例如,当您的 MVC 应用程序具有依赖于 ClassA 的 ClassD(来自 LibA)的 XController 时,在这种情况下,您应该只解析 XController。

于 2013-08-14T15:20:01.250 回答
2

完全同意史蒂文的回答,关于你的第四个问题:

问题 4:该建议是否也适用于任何其他层?还是假的?

在领域驱动设计中,领域层被认为是应用程序的核心,而 UI、数据库、基础设施层等其他层就像是附加层。这就是为什么域层将是主要的并且不参考其他层的原因。我希望这就是他们上述声明的意思。请看一下问题DDD 给出的图表:应该如何组织层?.

为了进一步阅读,我在这里有一篇关于 DI 的文章

如有进一步查询,请告诉我。谢谢。

对大卫第一条评论的回答:

数据存储库层具有根据http://martinfowler.com/eaaCatalog/repository.htmlhttp://msdn.microsoft.com/en-us/library/ff649690.aspx的存储库。

映射层应该像 Nhibernate 或实体框架一样具有 ORM ( http://en.wikipedia.org/wiki/Object-relational_mapping )。

数据存储库和映射是 DAL(数据访问层)的一部分,它们是可选模式,但最常用于访问数据。如果您没有复杂的 DAL...您可以在这里使用 JDBC 或 ADO.NE。

进一步了解 DI 如何在代码中工作......我发现的最佳位置是 Ninject 用户指南http://ninject.codeplex.com/wikipage?title=User%20Guide&referringTitle=Home,特别是那里给出的演练。

于 2013-08-14T15:57:41.670 回答