我在工作中与某人进行讨论。这些类和接口如下所示:
public interface ISomeInterface { }
public class ImplementationOfInterface : ISomeInterface { }
public class ClassThatUsesInterface {
private ISomeInterface _interface;
public ISomeInterface Interface {
get => _interface ?? new ImplementationOfInterface();
set => _interface = value;
}
}
我们有99%的时间会使用ImplementationOfInterface
。最后1%可能是单元测试目的。
我尝试阅读有关依赖性注入,依赖性反转原理,服务,SOLID以及诸如服务定位器模式/反模式,两步初始化反模式等不相关的东西,但没有发现任何描述这种方式。
已经清楚了SOLID中的D被违反了; “依赖倒置原则; 一个人应该“依赖抽象,而不依赖混凝土”。因为在单元测试中覆盖它很容易,或者如果您愿意的话也可以切换实现,这使我对此更加困惑。
即使它可能与SOLID中的D相对,并且在进行适当的依赖注入之后并没有真正执行任何操作,真的很难反对这种用法。
我个人建议通过构造函数注入实例,但是我的同事认为这是多余的工作,并且看不到好处。老实说,我很难同意,但是对此我仍然有不好的感觉。
您能否提出支持或反对使用此特定“ hack”的文章或强有力的论据?
答案 0 :(得分:4)
ClassThatUsesInterface
甚至需要知道 ImplementationOfInterface
存在的事实是一种代码味道。您可能需要为某个完全不相关的命名空间添加using
指令,以便对其进行编译,甚至可能是对其他项目或程序包或dll
的引用。因此,您的代码开始纠结,您的依赖项开始引起麻烦。
我意识到这是一个精简的演示示例,但是ImplementationOfInterface
只是偶然本身没有任何依赖关系。如果可以了怎么办?您会依次new
来吗?还有他们的依赖性..?然后,这表明您在这里违反了另一个SOLID原则-每次将ctor
args更改为ImplementationOfInterface
时,都需要修改此类。这违反了开放/封闭原则。
答案 1 :(得分:1)
使用构造函数注入依赖项。您不想在ClassThatUsesInterface
请注意,某些DI框架或实现不支持属性注入。例如,例如Asp.Net Core。
此外,像现在一样使用该属性,您还必须对属性的默认实现(它对类不应该知道,您现在正在耦合它)具有熟悉的知识,因为它是隐藏的。而如果您显式使用构造函数,那么所有人都将很清楚。