对需要参数的对象的依赖注入

And*_*rew 8 c# dependency-injection

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

这很好用,会产生这样结构很好的类:

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

   public Check CreateCheck()
   {
      //do the translation...
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,在某些情况下,映射具有许多不同的分组选项.结果,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...
   }
}  
Run Code Online (Sandbox Code Playgroud)

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

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

Aar*_*ght 13

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

换一种说法:

public Check CreateCheck(bool doTranslateStubData, bool doAttachLogo)
{
   //do the translation...
}
Run Code Online (Sandbox Code Playgroud)

这些参数是否必须通过构造函数传递?

(注意 - 如果你对此的回答是"有太多方法可以实现",那么部分问题可能是抽象太粗糙了).


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

public interface ICheckConfiguration
{
    bool AttachLogo { get; }
    bool TranslateStubData { get; }
}
Run Code Online (Sandbox Code Playgroud)

然后用构造函数注入它:

public CheckTranslator (IEmployeeService empSvc, IPaycheckService paySvc,
    ICheckConfiguration config)
{
    // etc.
}   
Run Code Online (Sandbox Code Playgroud)

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


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