【问题标题】:Constructor dependency hell构造函数依赖地狱
【发布时间】:2019-07-02 13:32:44
【问题描述】:

我尝试使用尽可能多的接口来进行良好的单元测试并更好地理解程序架构。

尽管我尝试遵循 SOLID 规则 - 我的类需要在构造函数中传递大量依赖项,这变成了地狱。

搜索使我找到了 IoC 容器,但实际上我不太了解何时使用它们。在构造函数中传递一个 NInject 内核看起来是一个愚蠢的想法,并且只使用 NInject 创建主类并不能消除构造函数中一堆参数的问题。

我无法减少构造函数中的依赖数量。我不明白如何正确使用 NInject 来减少构造函数参数。我该如何解决这个问题?

(不是最坏的例子)

public SomeConstructor(ISettings settings, INotification notification, IServer server, IPriceCache priceCache)
{
    Settings = settings;
    Notification = notificartion;
    Server = server;
    PriceCache = priceCache;
}

(这个解决方案看起来很糟糕)

public SomeConstructor(IKernel ninjectKernel)
{
    Settings = ninjectKernel.Get<ISettings>();
    Notification = ninjectKernel.Get<INotification>();
    Server = ninjectKernel.Get<IServer>();
    PriceCache = ninjectKernel.Get<IPriceCache>();
}

【问题讨论】:

  • 我不确定我是否理解,您的构造函数只有一个参数,即容器。如果您指的是您在类本身中拥有的依赖项的数量,那么这是另一个与代码耦合有关的问题,而不是这里提出的问题
  • @DavidPilkington 创建一个存储所有接口并将其传递给构造函数的中心类是个好主意吗?
  • 四个构造函数参数几乎不是地狱。甚至十个。不仅如此,我开始有点担心——不是关于 DI 方法,而是关于我的对象模型,因为它可能表明该类正在做太多事情(参见Single Responsibility Principle)。要回答您的问题,不,这不是一个好主意; creating a central class is actually an anti-pattern.

标签: c# constructor dependencies


【解决方案1】:

使用 IoC / DI 的原因之一是摆脱生命周期责任 - 即组件应该 请求 依赖项(通过例如构造函数注入或属性注入),但不应该拥有他们。

因此,应该有一些其他类,通常称为某种类型的 container,它管理生命周期范围和依赖关系。

在(理想的)组织良好的架构中,您永远不会为服务调用解析 - 您在容器中注册所有服务,并让它们存活 - 然后容器将为它们创建组件并解决必要的依赖关系(维护创建和处置,当必要的,在不同的生命周期范围内)。

所以你做的几乎所有事情都“正确”,但只是缺少这个“容器”概念。

【讨论】:

  • 能否提供样品容器的链接?
  • 我认为你确实使用容器;所有你需要意识到你需要在任何地方使用它。因此,您不需要手动创建服务,而是需要在任何地方(几乎?)请求它们的注入。 IoC 容器提供与 ASP.NET MVC 等框架的集成,因此框架将使用容器本身。我不熟悉 Ninject,但他们的文档看起来很有希望。例如关于生命周期范围github.com/ninject/Ninject/wiki/Object-Scopes 的这一部分和扩展部分中的github.com/ninject/Ninject/wiki/Why-Use-Ninject 提供了各种框架集成的列表。
【解决方案2】:

如果你不想要构造函数中的任何东西,那么Ninject 允许你通过使用属性来使用名为Property Setter Injection 的东西。它看起来像这样:

class Samurai 
{    
    [Inject]
    public IWeapon Weapon { private get; set; }

    public void Attack(string target) 
    {
        this.Weapon.Hit(target);
    }
}

但正如我在上面的评论中提到的。所有这些基本上都是一样的,只是因为你没有在你的构造函数中包含项目并不会改变你觉得你的代码有大量依赖项的事实。

【讨论】:

  • 一个好的代码可以在构造函数中需要这么多依赖吗?还是这可能表明我的代码不好?
  • @Andrew 您提到您尝试关注 SOLID。好吧,“S”代表单一职责原则。所以我想你需要问问自己,你的班级做得太多了吗?您的班级很可能确实需要这一切。只有你知道完整的上下文。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多