擁抱.NET Core系列:依賴注入(1)

依賴注入時編程手段中解耦和封裝的一個很是重要的手段,我本人已經到了沒有DI沒法編寫項目的程度了,在.NET Framework中微軟並無在FCL中引入DI,雖然推出了「Unity」。而在.NET Core中DI幾乎是全部組件的標配可見DI有多麼的重要,本節主要簡單介紹下微軟在.NET Core中加入的DI組件。java

前言

DIP、IoC、DI

提及DI不得不提IoC這個模式,不少人會把DI和IoC混爲一談,但其實這二者是概念和實現的關係。編程

依賴倒置原則(DIP):軟件設計原則,要依賴於抽象,不要依賴具體實現。函數

控制反轉(IoC):一種實現DIP原則的模式。工具

依賴注入(DI):IoC的具體實現。ui

DIP就比如一個目標一個法則。搜索引擎

IoC就比如是論文,「應該怎麼作才能遵循DIP」spa

DI就比如是實際的產品,「落實到具體的語言的工具」設計

關於這個比喻可能不是很準確,你們能夠使用搜索引擎去了解更爲詳細的差別。3d

在.NET

在我接觸的不少.NET項目中,不多有人使用DI,更別提像Orchard那樣把DI用得出神入化。而複雜的代碼很大一部分的緣由是沒有引入DI。在java中幾乎從剛入門的新手都使用Spring提供的DI。blog

依賴注入生命週期

生命週期是指對服務實例的存活狀態控制,"Microsoft.Extensions.DependencyInjection"提供了一個枚舉定義了三種生命週期狀態。

類型 描述
Singleton 單例服務,從當前服務容器中獲取這個類型的實例永遠是同一個實例。
Scoped 域內單例,爲每一個做用域建立一個服務實例,也就是說域內單例(域相似子容器)。
Transient 瞬態,從服務容器中每獲取一次建立一個新的實例。

用例服務

image

代碼以下:

image

註冊服務的N種姿式

image

其實能夠很容易的看出,服務註冊是經過建立一個「ServiceDescriptor」來完成的,而其它方式的註冊只不過是基於一個方法的封裝而已,讓使用者能夠更爲方便的進行服務註冊。

咱們能夠經過不少手段去註冊一個服務,但這裏推薦你們優先使用擴展方法進行服務註冊,由於這樣的代碼更易讀。反射循環注入時能夠使用其它方式。

服務使用

首先咱們來看一下服務提供者提供的方法簽名。

image

image

能夠發現與服務註冊同樣,基於同一個方法提供了不少擴展方法讓使用者更加便捷的獲取服務。

咱們先來看「GetService<T>」與「GetRequiredService<T>」這兩個方法。

這兩個方法很是接近,惟一不一樣的是GetRequiredService會在找不到服務的時候拋出異常,而GetService在找不到服務時會返回null。

image

「GetServices」這個方法是用來獲取多個服務實例,該方法會返回該類型註冊的多個服務實例。咱們來看個例子:

image

服務的生命週期

image

咱們能夠經過運行結果很好的理清各個生命週期的用意。下面用一張圖來講明較複雜狀況下「scope」的服務結果。

image

小技巧

註冊支持延遲加載的服務

開發過程當中常常有一種狀況,服務A的A方法依賴了服務B,而服務A的B方法依賴了服務C,這時候你就得在構造函數上同時聲明服務B和C,就像這樣。

image

這在其它DI組件中很是常見,好比autofac。而在如今咱們須要這樣作:

image

image

寫在最後

.NET技術棧QQ羣:384413261(點擊加入.NET Group

相關文章
相關標籤/搜索