查看原文
其他

深入浅出ASP.NET Core:依赖注入

DotNet 2019-07-31

(给DotNet加星标,提升.Net技能


转自:张飞洪

cnblogs.com/jackyfei/p/9902505.html


从UML来理解依赖


1.1、什么是依赖


我们先看下图



可以简单理解,一个HomeController类使用到了DBContext类,而这种关系是有偶然性,临时性,弱关系的,但是DBContext的变化会影响到HomeController


1.2、显示依赖和隐式依赖


先看显示依赖代码:



显示依赖通过构造函数,很清楚的描述了HomeController类都依赖了哪些对象,这样就可以很好的管理这些依赖。而隐式依赖的缺点刚好就是显示依赖的优点。我们看下面的隐式依赖:



如果一个类有上千行代码,到处都充斥着该类型的代码,这些代码就像隐藏的病毒一样,无处不在,可以想象后续的变化和修改是多么的恐怖。


1.3、依赖倒置


依赖倒置的概念其实很简单,一句话就讲完了:我们要依赖抽象,而不依赖具体实现。什么是抽象?比如接口,抽象类就是。


依赖抽象的目的是什么?封装变化!因为所有实现接口的实现都可以互相替换。



如上图所示,当数据库DapperUserRepository切换到EfUserRepository,对HomeController类可以无需任何修改,就可以平滑切换过去。反之,则更改的面就会非常大。


再看下面的代码,OrderController依赖接口IUserRepository就是依赖倒置的表现。



从单元测试来理解


也许你会说,我的变化没有那么频繁,不需要那么麻烦。那么你是否考虑过,有可能自己的代码需要进行单元测试?如果存在这种可能,那么依赖注入是你必须要做的事。


2.1、控制反转


我们再看下面这个代码的问题



虽然OrderController依赖的是接口IUserRepository,满足依赖倒置原则,但是构造函数却依赖的是具体实现类UserRepository,这种做法属于硬编码,仍然无法满足未来变化带来的修改,怎么办?接下来我们来讲控制反转这个相对难以理解的概念。


先说反转,到底反转的是什么?我们知道OrderController依赖的对象UserRepository是在构造函数内的生成的。如何能够把该对象的生成交给外部去决定生成呢?可以的!这种转移对象生成的方式就是控制反转。


简而言之,反转的是控制权,即依赖对象生成的控制权。是自己决定生成还是交由别人去决定生成。


所以上面的代码,修改如下:



以上的代码才达到真正的控制反转,UserRepository对象的生成完全交由外部进行控制,交给变化去控制。


这样有什么好处呢?交给外部生成的最大好处是想要生成什么对象可以自由控制,这样还是为了将来对象生成的可替换,比如数据库访问对象的变更;单元测试的实现类替换等等。


2.2、单元测试


有了上面的控制反转,我们的单元测试就方面很多了。



我们可以看到,在数据库无法连接的时候,我们可以使用MemoryUserRepository进行替换单元测试,非常方便。


推荐阅读

(点击标题可跳转阅读)

ASP.NET Core 依赖注入深入讨论

ASP.NET Core 2.0 依赖注入

ASP.NET Core 2.0 使用Autofac实现IOC依赖注入


看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存