【问题标题】:Dependency Injection for objects that require parameters需要参数的对象的依赖注入
【发布时间】:2010-04-03 23:36:29
【问题描述】:

我们所有的报告都是根据从我们的域对象转换而来的对象图创建的。为了实现这一点,我们为每个报告都有一个 Translator 类,并且一直在使用依赖注入来传递依赖项。

这很好用,并且会产生像这样结构的漂亮类:

public class CheckTranslator : ICheckTranslator
{
   public CheckTranslator (IEmployeeService empSvc
                         , IPaycheckService paySvc)
   {
      _empSvc = empSvc;
      _paySvc = paySvc;
   }

   public Check CreateCheck()
   {
      //do the translation...
   }
}

但是,在某些情况下,映射具有许多不同的分组选项。结果,c-tor 将变成类依赖项和参数的混合体。

public class CheckTranslator : ICheckTranslator
{
   public CheckTranslator (IEmployeeService empSvc
                         , IPaycheckService paySvc
                         , bool doTranslateStubData
                         , bool doAttachLogo)
   {
      _empSvc = empSvc;
      _paySvc = paySvc;
      _doTranslateStubData = doTranslateStubData;
      _doAttachLogo = doAttachLogo;
   }

   public Check CreateCheck()
   {
      //do the translation...
   }
}  

现在,我们仍然可以对其进行测试,但它不再真正适用于 IoC 容器,至少以干净的方式。另外,如果每次检查的设置不同,我们就不能再调用两次 CreateCheck。

虽然我认识到这是一个问题,但我不一定看到正确的解决方案。为每个类创建一个工厂似乎有点奇怪......或者这是最好的方法吗?

【问题讨论】:

  • 您能否详细说明“不再真正适用于 IoC 容器”?你用的是什么容器?
  • 不知何故,我无法理解依赖注入的奇妙之处,以及为什么它甚至是一个有自己花哨名称的模式。是什么阻止您将 bool 参数转换为属性?
  • @Hamish:它们是构造函数参数,因为它们是强制性的。将它们放在构造函数中会强制在使用组件之前明确设置它们。
  • @Hamish:这里有很多关于 SO 解释依赖注入的问题。
  • @Mauricio - 这不是 IoC 容器的问题,而是我们混合了可变和非可变依赖项。在第一种情况下,容器可以担心依赖关系图,在第二种情况下,它不再将依赖关系拉入图中,因为每次调用 CreateCheck 都需要构建 CheckTranslator(以设置属性)。

标签: c# dependency-injection


【解决方案1】:

这里是在黑暗中拍摄的,但是您可以将这些参数移到方法中吗?

换句话说:

public Check CreateCheck(bool doTranslateStubData, bool doAttachLogo)
{
   //do the translation...
}

那些参数要通过构造函数传入吗?

(注意 - 如果您对此的回答是“有太多方法无法实现”,那么部分问题可能是抽象过于粗糙)。


另一种选择(如果不了解域模型和注入模式就很难说)是引入一个本身由注入器管理的参数对象:

public interface ICheckConfiguration
{
    bool AttachLogo { get; }
    bool TranslateStubData { get; }
}

然后用构造函数注入这个:

public CheckTranslator (IEmployeeService empSvc, IPaycheckService paySvc,
    ICheckConfiguration config)
{
    // etc.
}   

应该足够了。然后,您可以创建一个具体的 CheckConfiguration 类,该类在其构造函数中采用这两个 bool 属性,并配置您的容器以基于更高级别的 DI 参数创建参数对象(接口)的不同实例。


我想我应该提到的最后一件事是,仅仅因为您正在使用 DI 并不意味着 一切 都必须由容器管理。如果只有一种“翻译器”,那么以临时方式创建 CheckTranslator 对象并不是一件坏事。只要翻译器仍然依赖 abstractions,它在这里所做的,那么也许你根本不应该注入它,只需让更高级别的支持 DI 的类临时创建它们。

【讨论】:

  • 我现在太累了,无法再次编辑我的答案,但还有另一种可能性,即使用抽象工厂模式并注入[I]CheckTranslatorFactory。这将是创建带有参数的未知具体类型的CheckTranslatorICheckTranslator 对象的有效方法;不是注入实际的翻译器实例,而是注入工厂,并让不同的工厂负责创建不同的翻译器子类型。仅当您打算对 CheckTranslator 使用多态性时才真正必要/有用。
  • 使用 ICheckConfiguration 是个好主意。为默认情况传入 Null 模式实现,为其他情况传入真实实现。
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 2012-11-17
  • 2020-01-19
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
相关资源
最近更新 更多