Asp.net core自定義依賴注入容器,替換自帶容器


依賴注入

       在asp.net core程序中,眾所周知,依賴注入基本上貫穿了整個項目,以通用的結構來講解,控制器層(Controller層)依賴業務層(Service層),業務層依賴於倉儲層(Repository層),而其他層級中也或多或少的使用了依賴注入,在這里不過多的對於依賴注入概念上不進行講解,如果有不了解的同學,可以在微軟官網或者在搜索引擎搜索依賴注入相關概念,本文主要講解如何在asp.net core中實現自己的依賴注入容器,並且希望更多的同學能夠去閱讀源碼碼,因為源碼中暴露的一些抽象類或者接口向開發者提供了方便開發者自定義或者拓展的口子。好了,不多啰嗦,我們開始。

First IServiceProviderFactory接口

       用過Autofac的同學都知道在asp.net core3版本之后,Autofac的使用方式稍微發生了一些變化,首先需要在Program.cs文件中需要使用Host.UseServiceProviderFactory方法,那實際上這個方法就是讓開發者能夠去實現自定義的依賴注入容器的一個拓展方法,我們可以查看一下這個方法的定義,注意看有個重點的接口就是IServiceProviderFactory接口,這個接口實際上是指定服務提供者的一個抽象工廠泛型接口,這是實現自定義IOC中最重要的接口之一,也是最開始的一步,實際上,實現自定義依賴注入容器,只需要實現兩個接口就可以實現自定義容器,可以看到這個方法有兩種參數機制一種是直接傳入對應的 實現類,另一種是使用委托的方式去創建對象,並且傳入了一個HostBuilderContext的對象,我們會使用這種方式去實現。

 

 

Second IServiceProvider接口

 

 

 

 

 

       我們可以看到這個IServiceProviderFactory接口有兩個實現方法,一個是CreateBuilder方法,里面傳入IServiceCollection變量,另一個方法是CreateServiceProvider方法,傳入我們這個接口指定的容器類的對象,其中IocContainer類不依賴於任何一個抽象,第一個方法的作用就是去構造這個容器的對象,需要返回我們指定的類型的對象,即是這個類是代表着容器,存放服務的,第二個方法是將上面構造的容器對象傳入進來,並且返回我們指定的服務提供者,那概念很清晰了,第一個IServiceProviderFactory接口是用來指定我們的容器是哪一個類是我們的容器,以及哪一個是我們的服務提供者,那實際上的IServiceProvider就是第二個重要的一個接口了,這個接口是只有一個方法,GetService方法,參數是一個Type,代表着我們是要去獲取哪一個類型的參數,返回值是Object,返回下層依賴者所需要的具體的一個對象。

 

Three 遵循規則實現自定義容器

        那實際上自帶的依賴注入容器也是遵循這種規則去實現的,它提供了一個自帶的一個ServiceProvider的類去創建對象,那大家都知道啟動一個Core的一個程序,自帶的一些依賴對象都有一百多個,那大家可能會覺得,讓自己去寫這種一百多個對象的創建,並且類別還是core的開發者所沒有暴露出的類型,創建起來會很麻煩,並且還存在各種依賴,讓大家覺得可能自定義依賴注入容器可能很難,實際上,剛開始的時候我也是這么想的,表達式樹在我去年十二月份的時候就開始寫代碼了,只是今年才上傳到博客,那實際上,自定義容器我也是去年開始研究的,剛開始也是寫了很多判斷因為它內部啟動的時候大的依賴了兩個東西一個是配置的IConfiguration,還有一個就是一個Host的一個類,下面又依賴了很多很多的類,感覺創建起來很麻煩,后來在想到了反射是可以獲取程序運行時的元數據並且去構造某個類型,那實際上,我們是可以用反射去實現一種投機取巧的方式去實現自定義依賴注入容器,那就是將啟動所依賴服務由自帶的ServiceProvider去進行提供和創建,一些項目開發中使用的服務由我們去進行管理,那說到這,已經有很多同學知道了怎么去進行了,我們看代碼。

 

          上圖中,我們可以看到Provider類是實現了IServiceProvider的接口,並且實現了GetService的方法,可以看到,我使用的方式是去用反射去獲取自帶的ServiceProvider的構造函數,然后創建這個對象,並且在GetService方法中,首先去判斷能否從自帶的Provider去獲取和創建對象,如果獲取不到,那說明是我們項目中所需要的類型,從而使用我們自定義的容器去進行獲取對象,默認的獲取不到是因為我們在創建ServiceProvider對象的時候傳入了IServiceCollection的對象,這里所包含的就是啟動Core程序所需要的依賴的集合,這樣我們就可以保證,程序啟動的時候是可以正常啟動的,然后在運行中,請求中所需要的服務類型是由我們自己去創建對象的,所以這樣就實現了簡單的IOC依賴注入容器,並且替換掉自帶的容器。

Four 控制器層的屬性注入以及拓展容器實現屬性注入和一接口多實現

        按照我文章剛開始的時候所說,微軟給我們暴露了很多供我們自定義的接口和 抽象類,那如果需要在控制器層實現屬性注入那怎么辦呢?那實際上還有一個接口,用來讓我們去創建控制器,那就是IControllerFactory接口,這個接口有兩個方法,一個是CreateController方法和ReleaseController方法,顧名思義就是一個是創建控制器,一個是銷毀控制器,那我們可以在第一個方法去實現控制器層的屬性注入以及一個接口多實現該怎么去獲取的思路,如果是屬性注入,我們是需要去創建一個特性用來標記這個屬性是用來從容器中獲取對象的,我們可以在控制器層或者其他類中使用類似的方法去操作屬性注入賦值,如果是一個接口多實現呢,也是需要去定義兩個特性,一個特性標記在實現類上面,並且構造函數中有一個string類型的參數,用來標記是在容器中 注入的時候使用某個名稱用來標識這個類型,其次在我們進行獲取這個類型的時候需要在參數或者屬性用我們定義的第二個特性標記這個參數或者屬性是從容器中獲取的是哪一個名稱哪一個類型的對象,這樣就可以實現一個屬性注入和一個接口多實現的一個操作。

 

 

 

總結

        以上是我個人實現自定義IOC的一個解決思路,並且在net core5以及net core6中實現,且5到6實現了無縫升級,沒有任何錯誤,希望能夠對各位讀者有所幫助。還是希望眾多道友能夠多解讀源碼,去查看core框架開發者提供給我們暴露給我們的自定義拓展的一些接口和抽象類。后面我依舊會持續更新core自定義相關的東西,會包括配置還有日志等其他方面的東西,多線程方面的代碼已經寫完,可以在QQ群6406277群文件中進行查找,也可以查看哪個net群有叫四川觀察的,那個就是我。IL后面我也寫了很多東西,后續也會一一奉上。在此,謝謝各位看官瀏覽。

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM