【问题标题】:Dependency Injection with Non-Classes非类的依赖注入
【发布时间】:2011-11-19 18:07:35
【问题描述】:

我对依赖注入有点陌生。我已经为一些将其依赖项作为构造函数中的参数传递的类设置了它,但我有一些构造函数采用像Stringboolean 这样的原语。显然,如果我要对该类使用依赖注入,则需要从构造函数中删除这些。

对于这种情况,什么是“最佳”做法?让构造函数只获取依赖项并为类所需的所有原语提供一个 setter 方法?

【问题讨论】:

  • 您的目标是哪种技术? 。网?爪哇?还有什么?
  • 你想分享一个具体的例子吗?

标签: language-agnostic dependency-injection


【解决方案1】:

如果我要对该类使用依赖注入,显然需要从构造函数中删除这些

不,不是“显然”。您可以保留这些参数以及注入依赖项。

如果类需要这些参数来正确初始化,它们需要是构造函数的一部分。

【讨论】:

  • 我知道显然会咬我:) 所以如果我在构造函数中确实需要这个,我该如何使用依赖注入?
  • @skaz - 您只需传入依赖项。或者您的意思是询问 IoC 容器?
  • 是的,也许这就是术语,我不知道。我试图通过在类外部定义对象图来注入依赖项。请参阅我对史蒂文回答的评论,以了解我正在尝试做的事情。感谢您的帮助。
  • @skaz - 我想我现在明白你的意思了。您始终可以为依赖注入进行属性注入而不是构造函数注入。
  • 如果我有一个Resource 封装了一个String(这是该类所代表的资源),你认为有一个setResource 方法有意义吗?我知道这是解决问题的方法,但感觉有点奇怪,我不会在构造时设置实例的真正本质。这只是我必须使用(我现在相信被称为)控制反转的权衡吗?再次感谢。
【解决方案2】:

我的观察是,在大多数情况下,具有同时采用依赖项和原语的构造函数的类会破坏 Single Responsibility Principle 或至少导致设计不太干净,从而导致容器配置更加脆弱和更难理解。

在大多数(如果不是全部)情况下,这些原语是配置值,例如连接字符串、调试选项等。

您可以通过几种方式更改设计来解决此问题:

  1. 如果您要破坏 SRP,请将代码提取到它自己的类型中。以this example 为例,其中NotifyCustomerHandler 采用string notificationServiceUrl,而string 应该被封装成某种NotificationService
  2. 另一个选项是将一个类型的配置值提取到它自己的类型中。对于NotifyCustomerHandler,它可能依赖于INotifyCustomerHandlerConfiguration。过去,我曾经有一个单一的IMyApplicationConfiguration 接口,其中包含应用程序所需的所有配置值,但我得出的结论是这是一个坏主意。这打破了Interface Segregation Principle,您的单元测试将开始在可读性和可维护性方面受到影响。
  3. 当您没有破坏 SRP 并且注入配置对象不切实际时(当您只有一个原语或获得太多配置接口,或者您只是不喜欢该选项时),您可以更改这些构造函数公共属性的参数。这将允许您(对于大多数容器)注册一个委托,该委托将在创建后配置实例,编译器可以为您验证这一点。

【讨论】:

  • 感谢您深思熟虑的回答。我的构造函数当前采用包含 JSON 或 XML 的字符串。我可以将它提取到它自己的类型中,也许是Resource 或其他东西。但是要将String 放入此类以构建Resource,似乎在尝试构建Resource 对象时我会遇到同样的问题。看来我唯一的选择是#3,创建一个我可以设置的属性 - 这感觉不对。
【解决方案3】:

类应该获取它需要的任何依赖项,以执行其功能。它将一些任务委托给其他服务,以及原始依赖项(通常是一些配置值)。

任何重要的容器都可以满足这种情况并允许您执行此操作。 Here's for example how Castle Windsor does it.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    相关资源
    最近更新 更多