Ninject:用于注入多个依赖项的注入模式应该使用哪一个?

3
如果我有10个需要注入的依赖项,而不想在构造函数中有10个参数,那么我应该使用哪种注入模式?
public class SomeClass
{
    private IDependency1 _dependency1;
    private IDependency2 _dependency2;
    private IDependency3 _dependency3;
    //...
}

我应该使用setter方法注入吗?
public class SomeClass
{
    private IDependency1 _dependency1;
    private IDependency2 _dependency2;
    private IDependency3 _dependency3;
    //...

    [Inject]
    public void SetDependency1(IDependency1 dependency1)
    {
        _dependency1 = dependency1;
    }
    //...
}

或者属性注入?
public class SomeClass
{
    [Inject]
    public IDependency1 Dependency1 { private get; set; }
    [Inject]
    public IDependency2 Dependency2 { private get; set; }
    [Inject]
    public IDependency3 Dependency3 { private get; set; }
    //...
}

根据Ninject维基,仅编写像上面那样的属性被认为是不良实践,但它与上述setter方法注入不是一样的吗?只是代码更少吗?
哪种模式在这种情况下最有意义?
1个回答

9
构造函数注入始终是执行依赖注入的首选方式。当无法使用构造函数注入时,例如处理依赖循环(其中A依赖于B,而B又依赖于A),您应该仅回退到属性注入。
您可能会问这个问题的原因是,您在编写和维护具有许多参数的构造函数时感到不舒服。
拥有那么多参数是一种反模式(构造函数过度注入反模式),但解决这个问题的方法不是回到属性注入。通常情况下,当有这么多依赖时,相关类做得太多了;它违反了单一职责原则。当违反SRP时,拥有尴尬数量的依赖实际上将是最小的问题。违反SRP的代码更难理解、维护和测试。我可以从经验中谈论这个问题。每当我发现自己无法舒适地为一个类编写单元测试时,我的设计就有问题。除了SRP之外,还有四个重要原则,合并在SOLID首字母缩写中。遵循这些原则,你将成为一个更快乐、软件更易于维护的程序员。
当一个类违反SRP时,通常意味着它应该分裂成多个只有一个职责的类。这样做,您会看到依赖关系的数量减少。

1
+1 个好答案。唯一我能想到的补充是,如果你看到依赖项成群结队地移动,它们通常会带着相关的代码 - 这些代码应该成为自己的东西(这基本上就是你所说的,只是希望它能填补 OP 的空白)。 - Ruben Bartelink
例如,当您将许多IRepository<T>实现注入到服务中时。在这种情况下,您缺少一个IUnitOfWork抽象层。@RubenBartelink,我认为这就是您所说的“成群结队旅行”的意思。如果我误解了,请纠正我。 - Steven
1
我不会选择那个例子(或者引入Repository,因为这是一个非常具有歧义的东西,不同的人可能有不同的理解,同时和太多的repositories打交道也不是一个好兆头...)。如果你经常需要FrobGobSob,但有一段代码从Gob获取了一些东西并传递给了Sob,那么很可能缺少1、2或3个依赖关系涉及的抽象。这不是一个自动的过程——你要将其视为一种"味道",然后在你的代码库中寻找使用模式的共性。 - Ruben Bartelink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接