如何在.NET中处理构造函数的过度注入

时间:2011-01-05 11:29:06

标签: language-agnostic dependency-injection

如果已经讨论过这个问题,我很抱歉,但我并没有真正找到我想要的东西。我面临的问题更多是关于模式和设计选择而不是.NET本身。我想建议你知道从哪里开始我的重构。

今天我在我的实际应用程序中打开了一个类,发现它有13个由构造函数注入的依赖项!事实上,每个开发人员都在他正在编写的方法中添加了所需的依赖性。

我对DI的理解之一是,当我们通过构造函数注入依赖项时,它意味着它是一个强制依赖项,应该在类的所有方法中使用。如果我们只需要在给定类的一个方法中使用特定依赖项,那么它对您意味着什么?

  • 给定的课程做得太多了?我应该考虑创建一个只需要依赖的新类型吗?
  • 我应该按财产注入?但是在那个特定的方法中,依赖是强制性的,所以我认为这不是一个好的选择。
  • 我应该按方法注射?

找到合适的平衡点很困难。实际上,有时候不可能以干净的方式封装巴哈维尔。

我正在考虑创建类似服务聚合器的东西,以隐藏其中一个相关的依赖关系,但是如果你有其他建议则想要。提前谢谢。

5 个答案:

答案 0 :(得分:25)

你是对的:如果你需要在一个类中注入13个依赖项,那么你肯定会违反Single Responsibility Principle切换到属性注入无法帮助,因为它不会减少依赖项的数量 - 它只会暗示这些依赖项是可选的而不是强制的。

基本上,有两种方法可以解决这类问题:

  • Refactor to Facade Services。这基本上是非破坏性重构,因为它维护了Controller的功能。但是,它将责任更改为协调/编排服务之间的交互,而不是管理实施的细节。
  • 将课程分成独立的课程。如果每个服务由不同的开发人员引入以支持方法的子集,则表明低内聚。在这种情况下,最好将类拆分为几个独立的类。

特别是对于ASP.NET MVC,您可能不希望拆分Controller,因为它会更改您的URL方案。这很公平,但考虑一下这意味着什么:这意味着Controller的单一责任应该将URL映射到应用程序代码。换句话说,这就是控制器应该做的所有事情,然后正确的解决方案就是重构为Facade Services

答案 1 :(得分:10)

仅仅因为依赖是强制性的并不意味着它应该在所有类的方法IMO中使用。它应该在逻辑上是类本身配置的一部分。

另一方面,如果一个类有13个依赖项,那么它可能做得太多了。这些依赖项中的任何一个在逻辑上属于一起吗?也许依赖本身应该是“更大的” - 或者很可能你的班级应该做得更少。

答案 2 :(得分:4)

这听起来像是一个具有太多依赖关系的类的情况,即它是一个神级。尝试将其分解为更多离散的职责。

答案 3 :(得分:0)

如果你的班级有13个依赖项,你肯定有问题。显然,你的班级负有太多责任。 Marc Seemann在他的书“.NET中的依赖注入”第6.4段中讨论了这个问题。如果你的类在构造函数中开始有3个参数,你必须开始怀疑。我班上还有一个职责吗?如果您的构造函数中开始有4个或更多参数,请通过开始使用外观或合成模式来重构您的类。

答案 4 :(得分:0)

它就是DI的工作方式。这是事实。所以接受它。它在像Pdf服务这样的服务中完全合法,看看这段代码:

public PdfService(ILocalizationService localizationService, 
        ILanguageService languageService,
        IWorkContext workContext,
        IOrderService orderService,
        IPaymentService paymentService,
        IDateTimeHelper dateTimeHelper,
        IPriceFormatter priceFormatter,
        ICurrencyService currencyService, 
        IMeasureService measureService,
        IPictureService pictureService,
        IProductService productService, 
        IProductAttributeParser productAttributeParser,
        IStoreService storeService,
        IStoreContext storeContext,
        ISettingService settingContext,
        IAddressAttributeFormatter addressAttributeFormatter,
        CatalogSettings catalogSettings, 
        CurrencySettings currencySettings,
        MeasureSettings measureSettings,
        PdfSettings pdfSettings,
        TaxSettings taxSettings,
        AddressSettings addressSettings)