dependency-injection - 依赖注入(inject)和/vs 全局单例

标签 dependency-injection .net-core singleton

我是依赖注入(inject)模式的新手。我喜欢这个想法,但很难将其应用到我的案例中。我有一个单例对象,我们称它为 X,我在程序的许多部分、许多不同的类中经常需要它,有时在调用堆栈的深处。通常我会把它实现为一个全局可用的单例。这是如何在 DI 模式中实现的,特别是在 .NET Core DI 容器中?我知道我需要将 X 作为单例注册到 DI 容器,但是我如何才能访问它呢? DI 将使用引用 X 的构造函数实例化类,这很好——但我需要 X 在调用层次结构的深处,在我自己的对象中,.NET Core 或 DI 容器对此一无所知,在使用 new 而不是创建的对象中由 DI 容器实例化。

我想我的问题是——全局单例模式如何与 DI 模式对齐/实现/替换/避免?

最佳答案

嗯,“new 是粘合剂”(Link)。这意味着如果您new 了一个实例,它就会粘附到您的实现中。您不能轻易地将它与不同的实现交换,例如用于测试的模拟。就像把乐高积木粘在一起一样。

如果您想使用适当的依赖注入(inject)(使用或不使用容器/框架),您需要以一种不将组件粘合在一起而是注入(inject)它们的方式来构建程序。

那时每个类基本上都处于层次结构级别 1。您需要记录器的实例吗?你注入(inject)它。您需要一个需要记录器的类的实例吗?你注入(inject)它。您想测试您的日志记录机制吗?很简单,您只需注入(inject)符合记录器接口(interface)的内容即可登录到列表中,在测试结束时您可以检查列表并查看是否包含所有必需的日志。这是您可以自动化的事情(与使用常规日志记录机制和手动检查日志文件相比)。

这意味着最后,您并没有真正的层次结构,因为您拥有的每个类都只是注入(inject)了它们的依赖项,而容器/框架或您的控制代码将决定实例化顺序的含义的对象。


就设计模式而言,请允许我观察一下:即使是现在,您也需要单例。现在在你的程序中,如果你有一个普通的全局变量,它就会起作用。但我猜你读过全局变量是“坏的”。设计模式是“好”的。既然你需要一个全局变量,而单例提供了一个全局变量,那么当你可以使用“好”的时候,为什么要使用“坏”呢?好吧,问题是,即使是单例,全局变量也不好。这是该模式的一个缺点,您必须吞下一只蟾蜍才能使单例逻辑正常工作。在你的情况下,你不需要单例逻辑,但你喜欢蟾蜍的味道。所以你创建了一个单例。不要用设计模式这样做。仔细阅读它们并确保将它们用于预期目的,而不是因为您喜欢它们的副作用或因为使用设计模式感觉很好。

关于dependency-injection - 依赖注入(inject)和/vs 全局单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53631662/

相关文章:

java - 为什么 Dagger 注入(inject)具体类?

c# - 内部有两个服务和依赖注入(inject)的外观 - 设计模式方法

c# - 将 IHttpContextAcessor 注入(inject)到 Controller 操作内的绑定(bind)模型中

AzureADB2C.UI - 登录后将用户重定向到页面

dependency-injection - 我如何构建既可以作为 OSGI bundle 又可以作为 WAR 运行的应用程序

dependency-injection - 使用 IoC 时我对接口(interface)抽象感到困惑

sql-server - 什么会阻止在 Docker 容器中运行的代码连接到单独服务器上的数据库?

singleton - celery :任务单例?

.net - .Net 中的单例模式是不可能的吗?

c++ - C++ Singleton没有为该文档加载符号