简体   繁体   English

注入的依赖项是公共可访问还是私有?

[英]Should injected dependencies be publicly accessible or private?

Should dependencies be stored to private fields or properties with private setters and public getters? 是否应将依赖项存储到具有私有setter和public getter的私有字段或属性? This applies to constructor DI. 这适用于构造函数DI。

To be clear, in the property example, I would not expect these to be added to an accompanying interface unless it made sense - ie they would only be visible in the implementation type: 为了清楚起见,在属性示例中,我不希望将这些添加到附带的接口,除非它有意义 - 即它们只在实现类型中可见:

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; }
}

I would always recommend private readonly fields, as long as there is no need to access the dependency from outside of the object. 我总是会建议private readonly字段,只要不需要从对象外部访问依赖项。 Treat your objects as "black boxes" and put as little as possible in their public interfaces. 将您的对象视为“黑匣子”,并尽可能少地放在他们的公共界面中。 This practice is better known as encapsulation principle or information hiding and also applies to injected dependencies: The less you expose, the more you reduce tight coupling between your class and your class' users. 这种做法更好地称为封装原则信息隐藏 ,也适用于注入的依赖关系:暴露的越少,您减少的类与类的用户之间的紧密耦合就越多。

Another principle that should be mentioned is modeling the behavior of objects: Tell, don't ask . 应该提到的另一个原则是对对象的行为进行建模: 告诉,不要问 If you need to get something done, ask the object to do it for you. 如果您需要完成某项任务,请让对象为您完成。 It will use its dependencies in the process. 它将在进程中使用其依赖项。 Asking for properties and doing the work yourself should only be the first choice for data objects (DTOs). 询问属性并自己完成工作应该只是数据对象(DTO)的首选。

This is also the reason for using constructor injection in the first place: Everybody would be doing property injection instead, if exposing dependencies as properties was best practice, as this would mean less code (we wouldn't need the constructors then). 这也是首先使用构造函数注入的原因:如果将属性作为属性公开是最好的做法,那么每个人都会进行属性注入,因为这意味着更少的代码(我们不需要构造函数)。

It depends purely upon whether you need to allow the consuming object to change the dependency during the lifetime of the consumed object. 它完全取决于您是否需要允许使用对象在使用对象的生命周期内更改依赖关系。

Using DI on the constructor is setting you up for two things: 在构造函数上使用DI可以为您做两件事:

  • it is defining a contract, saying "this class needs this specific dependency to operate" 它正在定义一个合同,说“这个类需要这个特定的依赖关系才能运行”
  • it allows you to easily manipulate the dependency that is used by injecting a different implementation (ie injecting mock implementations when unit testing, or you have a view that could take any of several viewmodels when using MVVM, etc.) 它允许您轻松地操作注入不同实现所使用的依赖项(即在单元测试时注入模拟实现,或者您在使用MVVM时有一个可以采用任何几个视图模型的视图等)

If you like to keep your objects immutable, then a public getter and private setter is the way to go. 如果你想让你的对象保持不变,那么就可以使用公共getter和私有setter了。 However things are not always that simple - an object may have a long life, and it is easy to have a scenario where you need to change the dependency. 然而事情并不总是那么简单 - 一个对象可能有很长的寿命,并且很容易有一个需要更改依赖关系的场景。

TL;DR: it depends. TL; DR:这取决于。 When you write large applications you'll find that you need to mix your approach - you'll have dependencies defined in the ctor(s), but for some of them you'll need the facility to change them after the object has been created. 当您编写大型应用程序时,您会发现需要混合使用方法 - 您将在ctor(s)中定义依赖项,但对于其中一些应用程序,您需要在创建对象后更改它们的工具。 。

I agree with @Frank you have to keep it private it is better for Testing and it give you a better object encapsulation. 我同意@Frank你必须将它保密,它更适合测试,它给你一个更好的对象封装。

imagine you have an interface need to access only the Bar class in this case your customer can do something Bar.Dependency.BadMethodBurnTheDevice(); 想象你有一个接口需要只访问Bar类,在这种情况下你的客户可以做一些事情Bar.Dependency.BadMethodBurnTheDevice();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM