注入的依赖项应该公开访问还是私有?

Should injected dependencies be publicly accessible or private?

是否应该将依赖项存储到具有私有 setter 和 public getter 的私有字段或属性?这适用于构造函数 DI。

明确地说,在属性示例中,我不希望将这些添加到随附的接口中,除非它有意义 - 即它们只会在实现类型中可见:

interface IFoo {
  void DoSomething();
}

class Foo : IFoo {
  private readonly IService dependency;
  public Foo(IService dependency) {
    this.dependency = dependency;
  }
}

class Bar : IFoo {
  public Foo(IService dependency) {
    this.Dependency = dependency;
  }

  public IService Dependency { get; private set; }
}

我总是推荐 private readonly 字段,只要不需要从对象外部访问依赖项即可。将您的对象视为 "black boxes" 并尽可能少地放在它们的 public 接口中。这种做法被称为 encapsulation principle信息隐藏 并且也适用于注入的依赖项:暴露的越少,减少的越多您的 class 和您的 class 用户之间的紧密耦合。

另一个应该提到的原则是建模对象的行为:告诉,不要问。如果您需要完成某件事,请让对象为您完成。它将在此过程中使用其依赖项。问属性自己做应该只是数据对象(DTO)的首选。

这也是首先使用构造函数注入的原因:如果将依赖项作为属性公开是最佳实践,那么每个人都会进行 属性 注入,因为这意味着更少的代码(我们不会那时不需要构造函数)。

这完全取决于您是否需要允许消费对象在消费对象的生命周期内更改依赖关系。

在构造函数上使用 DI 为您准备了两件事:

  • 它正在定义一个合同,说"this class needs this specific dependency to operate"
  • 它允许您通过注入不同的实现轻松地操纵所使用的依赖关系(即在单元测试时注入模拟实现,或者您有一个视图可以在使用 MVVM 等时采用多个视图模型中的任何一个)

如果您想保持对象不可变,那么 public getter 和私有 setter 是可行的方法。然而事情并不总是那么简单——一个对象可能有很长的生命周期,很容易出现需要改变依赖的场景。

TL;DR: 这取决于。当您编写大型应用程序时,您会发现您需要混合使用您的方法 - 您将在 ctor(s) 中定义依赖项,但对于其中一些,您将需要在创建对象后更改它们的工具.

我同意@Frank 的观点,您必须将其保密,这样更有利于测试,并且可以为您提供更好的对象封装。

假设您有一个界面只需要访问栏 class 在这种情况下您的客户可以做一些事情 Bar.Dependency.BadMethodBurnTheDevice();