依赖注入、组合根和入口点

Dependency injection, composition root, and entry points

我花了很多时间阅读这些文章(以及许多其他文章):

而且我仍在努力思考 DI 和 "wiring up the dependencies" 的概念以及 IoC 容器的 "auto wiring" 功能。

我想我了解依赖注入和控制反转的理论,并且我从 2016 年开始实施了此处显示的示例(我更新了代码以使用 PSR-11 并消除了对 container-interop包):

容器实例的应用见GitHublink:https://github.com/sitepoint-editors/Container

请注意,虽然此示例使用 PHP,但我试图独立于语言来理解 DI 的详细信息,因此欢迎使用任何语言。

有人可以解释手动连接依赖项和使用容器的自动连接功能之间的区别吗? SitePoint 文章简要提到了更高级的容器添加了自动连接功能,暗示该示例不包含此功能。有人可以解释 GitHub 页面上显示的应用程序以及它与核心 DI 和 IoC 概念的关系,例如组合根。

Can someone explain the difference between manually wiring up dependencies, and using a container's auto wiring functionality?

纯 DI 是在不使用 DI 容器的情况下应用 DI 的做法。这意味着您可以通过使用编程语言的 new 结构更新对象来构建对象图。例如,请参阅 C# 中的此示例(来自 listing 12.2 of Mark's book Dependency Injection Principles, Practices, and Patterns):

new HomeController(
    new ProductService(
        new SqlProductRepository(
            new CommerceContext(connectionString)),
        new AspNetUserContextAdapter()));

根据那本书,自动接线是:

the ability to automatically compose an object graph from maps between Abstractions and concrete types by making use of type information supplied by the compiler and the [runtime environment]. (see 12.1.2)

换句话说,使用 DI 容器,您将能够 'just' 将您的类型告诉容器,它会找出一个类型具有哪些依赖项,并且能够 'wire' 该类型及其依赖项。

考虑到前面的例子,清单 12.3 显示了如何只需要在容器中指定抽象和具体类型之间的映射:

var container = new AutoWireContainer();

container.Register(typeof(IUserContext), typeof(AspNetUserContextAdapter));
container.Register(typeof(IProductRepository), typeof(SqlProductRepository));
container.Register(typeof(IProductService), typeof(ProductService));
container.Register(typeof(CommerceContext), () => new CommerceContext(connectionString));

当你请求 HomeController 时,容器知道如何构建整个图形。

The SitePoint article briefly mentions that more advanced containers add the automatic wiring functionality

对我来说,Auto-Wiring 是将库变成 DI 容器的原因。至少不支持Auto-Wiring的东西不能称为DI Container。