抽象,实体和属性注入与构造函数注入

时间:2018-11-07 13:38:23

标签: c# oop design-patterns architecture

我在工作中与某人进行讨论。这些类和接口如下所示:

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”的文章或强有力的论据?

2 个答案:

答案 0 :(得分:4)

ClassThatUsesInterface甚至需要知道 ImplementationOfInterface存在的事实是一种代码味道。您可能需要为某个完全不相关的命名空间添加using指令,以便对其进行编译,甚至可能是对其他项目或程序包或dll的引用。因此,您的代码开始纠结,您的依赖项开始引起麻烦。

我意识到这是一个精简的演示示例,但是ImplementationOfInterface只是偶然本身没有任何依赖关系。如果可以了怎么办?您会依次new来吗?还有他们的依赖性..?然后,这表明您在这里违反了另一个SOLID原则-每次将ctor args更改为ImplementationOfInterface时,都需要修改此类。这违反了开放/封闭原则。

答案 1 :(得分:1)

使用构造函数注入依赖项。您不想在ClassThatUsesInterface

实例的生命周期中半途更改实现。

请注意,某些DI框架或实现不支持属性注入。例如,例如Asp.Net Core。

此外,像现在一样使用该属性,您还必须对属性的默认实现(它对类不应该知道,您现在正在耦合它)具有熟悉的知识,因为它是隐藏的。而如果您显式使用构造函数,那么所有人都将很清楚。