1. 程式人生 > >【asp.net core 系列】14 .net core 中的IOC

【asp.net core 系列】14 .net core 中的IOC

# 0.前言 通過前面幾篇,我們瞭解到瞭如何實現專案的基本架構:資料來源、路由設定、加密以及身份驗證。那麼在實現的時候,我們還會遇到這樣的一個問題:當我們業務類和資料來源越來越多的時候,我們無法通過普通的構造物件的方法為每個例項進行賦值。同時,傳統意義上的賦值遇到底層切換或者其他修改的時候,就需要修改大量的程式碼,對改變不友好。為了改變這種現狀,我們基於面向介面程式設計,然後使用一些DI功能和IOC框架。 # 1. IOC和DI 先來給大家解釋幾個概念,IOC全稱Inversion of Control,翻譯過來就是控制反轉,是面向物件程式設計的一種設計原則,用來降低程式碼之間的耦合度。所謂的控制反轉簡單來講就是將類中屬性或者其他引數的初始化交給其他方處理,而不是直接使用建構函式。 ```c# public class Demo1 { } public class Demo2 { public Demo1 demo; } ``` 對於以上簡單示例程式碼中,在Demo2類中持有了一個Demo1的例項。如果按照之前的情況來講,我們會通過以下方法為demo賦值: ```c# // 方法一 public Demo1 demo = new Demo1(); // 方法二 public Demo2() { demo = new Demo1(); } ``` 這時候,如果Demo1變成下面的樣子: ```c# public class Demo1 { public Demo1(Demo3 demo3) { // 隱藏 } } public class Demo3 { } ``` 那麼,如果Demo2 沒有持有一個Demo3的例項物件,這時候建立Demo1的時候就需要額外構造一個Demo3。如果Demo3需要持有另外一個類的物件,那麼Demo2中就需要多建立一個物件。最後就會發現這樣就陷入了一個構造“地獄”(我發明的詞,指這種為了一個物件卻得構造一大堆其他型別的物件)。 實際上,對於Demo2並不關心Demo1的例項物件是如何獲取的,甚至都不關心它是不是Demo1的子類或者介面實現類。我在示例中使用了類,但這裡可以同步替換成Interface,替換之後,Demo2在呼叫Demo1的時候,還需要知道Demo1有實現類,以及實現類的資訊。 為了解決這個問題,一些高明的程式設計師們提出了將物件的建立這一過程交給第三方去操作,而不是呼叫類來建立。於是乎,上述程式碼就變成了: ```c# public class Demo2 { public Demo1 Demo {get;set;} public Demo2(Demo1 demo) { Demo = demo; } } ``` 似乎並沒有什麼變化?對於Demo2來說,Demo2從此不再負責Demo1的建立,這個步驟交由Demo2的呼叫方去建立,Demo2從此從負責維護Demo1這個物件的大麻煩中解脫了。 但實際上構造地獄的問題還是沒有解決,只不過是通過IOC的設計將這一步後移了。這時候,那些大神們想了想,不如開發一個框架這些實體物件吧。所以就出現了很多IOC框架:AutoFac、Sping.net、Unity等。 說到IOC就不得不提一下DI(Dependency Injection)依賴注入。所謂的依賴注入就是屬性對應例項通過建構函式或者使用屬性由第三方進行賦值。也就是最後Demo2的示例程式碼中的寫法。 早期IOC和DI是指一種技術,後來開始確定這是不同的描述。IOC描述的是一種設計模式,而DI是一種行為。 # 2. 使用asp.net core的預設IOC 在之前的ASP.NET 框架中,微軟並沒有提供預設的IOC支援。在最新的asp.net core中微軟提供了一套IOC支援,該支援在名稱空間: ``` Microsoft.Extensions.DependencyInjection ``` 裡,在程式碼中引用即可。 主要通過以下幾組方法實現: ```c# public static IServiceCollection AddScoped