【问题标题】:When to use DI over abstract inheritance?何时使用 DI 而不是抽象继承?
【发布时间】:2015-08-26 08:35:22
【问题描述】:

我正在设计一个使用抽象属性来提供对字段的访问点的类。这是我的代码的 sn-p:

public abstract class PageBroker : WebBroker
{
    public abstract IPageProvider Provider { get; }
}

public class ArticleBroker : PageBroker
{
     public override IPageProvider Provider { get; } = new ArticleProvider();
}

我意识到我可以将其重构为使用 DI,如下所示:

public class PageBroker : WebBroker
{
    public PageBroker(IPageProvider provider)
    {
        this.Provider = provider;
    }

    public IPageProvider Provider { get; private set; }

    // implementation...
}

// no derived class, just new PageBroker(new ArticleProvider())

在什么情况下,一种技术比另一种更合适?

【问题讨论】:

  • 当类到函数属性的值必需时,应使用构造函数注入。当注入一个值是可选的(例如,有一个默认值或客户端的特定用途不需要该属性)时,应该使用属性注入。
  • @DStanley 对不起,这根本不是我的问题。我在问我是否应该创建属性abstract 以便派生类可以实现它,或者通过构造函数将其传递。这与 setter 注入无关。
  • 好吧,构造函数不是继承的,所以派生类必须以任何一种方式“覆盖”某些东西。所以我不确定你在寻找什么区别(除了 setter 和构造函数注入)。
  • @DStanley 谢谢,更新问题澄清。 (没有带有 DI 的派生类。)
  • 就个人而言,我会使用第二个,因为我可以使用外部资源来提供我的IPageProvider(几乎是 DI 的定义)。第一个的用途是,如果我有另一个理由证明 ArticleBroker 需要与 PageBroker 不同/继承。

标签: c# dependency-injection abstract-class


【解决方案1】:

我同意 BJ Safdie 的回答。

也就是说,我认为主要区别在于,在第一个实现中,ArticleBroker 耦合到了 IPageProvider 的特定实现(即 ArticleProvider)。如果这是有意的,我认为没有问题。但是,如果您想在运行时提供 IPageProvider 的实现(在生产代码中或通过模拟/伪造在单元测试中),那么注入依赖项是更好的选择。

【讨论】:

    【解决方案2】:

    这是关于优先组合而不是继承,这是一个很好的指导方针。我建议由于 PageBroker 有一个 IPageProvider,你应该使用 DI。该类的用户可以提供无需继承的替代实现,例如注入测试 IPageProvider。仅出于这个原因,我会选择 DI。

    如果存在基于 IPageProvider 的存在差异,例如在语义上使用不同的提供者需要来反映 is a 关系(PageBroker 的子类型),那么我会使用抽象类。

    【讨论】:

      【解决方案3】:

      如前所述,我将使用 DI 填充您的 Provider。也就是说,您希望通过抽象类获得什么?如果只是简单的注入 IPageProvider 那就真的没什么好说的了。

      但是,如果您心目中还有其他特定于 WebBrokers 或 PageBrokers 的常用方法,那么为什么不同时使用这两种方法呢?

      例如:

      public abstract class WebBroker
      {
          private IPageProvider _pageProvider;
      
          protected WebBroker(IPageProvider pageProvider)
          {
              _pageProvider = pageProvider;
          }
      
          public override void CommonThing(int someData)
          {
             var result = _pageProvider.CommonMethod(someData);
             //do something with result
          }
      }
      

      现在您所有的网络经纪人都有 CommonThing 方法,该方法使用 DI 传入的 _pageProvider。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-25
        • 2013-05-02
        • 1970-01-01
        • 2016-01-07
        • 1970-01-01
        • 1970-01-01
        • 2013-12-15
        • 1970-01-01
        相关资源
        最近更新 更多