当前位置: 首页 > 知识库问答 >
问题:

对使用IOC容器、服务定位器和工厂感到困惑

孟俊晖
2023-03-14

假设我有一个BaseForm,它依赖于ILoggerIResourceManager

  • 使用构造函数注入是解决这种依赖性的正确方法吗
  • 我是否必须在容器中注册我的BaseForm(及其“派生类型”),以便创建具有已解析依赖项的它们的实例?难道这一切都不复杂吗
  • 在服务定位器周围使用静态工厂是不是很糟糕
  • 撇开单元测试不谈,我真的会因为使用服务定位器反模式而受到惩罚吗

很抱歉一次问很多问题。我已经阅读了以下SO问题和许多其他问题,但阅读它们只会增加我的困惑:

  • 如何使用依赖注入而不是服务定位器
  • 依赖注入模式和服务定位器模式之间有什么区别
  • 如何避免服务定位器反模式

共有1个答案

方树
2023-03-14

如果可能的话,您应该始终使用依赖注入,因为它有一些明显的优势。然而,对于UI技术,并不总是可以使用依赖注入,因为某些UI技术(例如. NET空间、Win窗体和Web窗体)只允许您的UI类(窗体、页面、控件等)具有默认构造函数。在这种情况下,您将不得不回退到其他东西上,即服务定位器。

在这种情况下,我可以给你以下建议:

  • 对于不能由容器使用依赖注入创建的UI类,以及对于无论如何都不是单元测试的东西,只能返回到Service Locator。
  • 尝试在这些UI类中实现尽可能少的逻辑(作为只有视图相关内容的Humble对象)。这允许您尽可能多地进行单元测试。
  • 将容器包装在静态方法周围,以对应用程序的其余部分隐藏容器。当无法解析依赖关系时,请确保对此静态方法的调用失败。
  • 解析该类型(默认)构造函数中的所有依赖项。这允许应用程序在创建该类型时无法解析其依赖项时快速失败,而不是稍后单击某个按钮时。
  • 在应用程序启动期间(或使用单元测试)检查是否可以创建所有这些UI类型。这使您不必(通过打开所有表单)查看整个应用程序中的DI配置是否有错误。
  • 当容器无法构建类型时,没有理由在容器中注册它们。如果它们可以由容器创建(例如使用ASP.NET MVC Controller类),则显式注册它们会很有用,因为某些容器允许您预先验证配置,这将立即检测这些类型中的配置错误

除了单元测试,还有两个反对使用Service Locator的重要论点,Mark Seemann在其著名的博客文章Service Locator is an Anti-Pattern中给出了这两个论点:

  • 服务定位器“隐藏类的依赖关系,导致运行时错误而不是编译时错误”
  • 服务定位器“使代码更难以维护”
 类似资料:
  • 问题内容: 据我了解,当在工厂内部时,我返回一个注入到控制器中的对象。在服务内部时,我使用而不是返回任何东西来处理对象。 我当时以为服务 始终是单例 ,并且每个控制器都注入了一个 新的工厂对象 。但是,事实证明,工厂对象也是单例对象吗? 示例代码演示: 当改变的事实证明,在也发生了变化,比如是一个单身? 我的假设是在工厂的控制器中注入了新实例? 问题答案: 所有角度服务都是单例 : Docs(请参

  • 在说 Ioc 容器之前,我们需要了解什么是 Ioc 容器。 Laravel 服务容器是一个用于管理类依赖和执行依赖注入的强大工具。 在理解这句话之前,我们需要先了解一下服务容器的来龙去脉: laravel神奇的服务容器。这篇博客告诉我们,服务容器就是工厂模式的升级版,对于传统的工厂模式来说,虽然解耦了对象和外部资源之间的关系,但是工厂和外部资源之间却存在了耦和。而服务容器在为对象创建了外部资源的同

  • bind 绑定 欢迎关注我的博客:www.leoyang90.cn bind 绑定是服务容器最常用的绑定方式,在 上一篇文章中我们讨论过,bind 的绑定有三种: 绑定自身 绑定闭包 绑定接口 今天,我们这篇文章主要从源码上讲解 Ioc 服务容器是如何进行绑定的。 /** * Register a binding with the container. * * @param string|arra

  • 当更改中的时,发现中的也会更改,例如是单例? 我的假设是,一个新的实例被注入到带有工厂的控制器中?

  • 我知道容器是应用程序和主机(托管运行进程)之间的一种隔离形式。我还知道容器映像基本上是运行时环境的包(希望我得到了正确的)。让我困惑的是,当他们说Docker图像不保留状态时。因此,如果我创建一个带有数据库(如PostgreSQL)的Docker映像,当我停止容器并重新启动时,所有数据不会被清除吗?为什么要在Docker容器中使用数据库? 我也很难掌握LXC。在另一个问题页面上,我看到: Linu

  • 首先欢迎关注我的博客: www.leoyang90.cn 服务容器对对象的自动解析是服务容器的核心功能,make 函数、build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abstract) { $abstract = $this->getAlias($abstract); if (isset($this->deferredSer