asp.net core自定义依赖注入容器,替换自带容器
依賴注入
? ? ? ?在asp.net core程序中,眾所周知,依賴注入基本上貫穿了整個(gè)項(xiàng)目,以通用的結(jié)構(gòu)來講解,控制器層(Controller層)依賴業(yè)務(wù)層(Service層),業(yè)務(wù)層依賴于倉儲(chǔ)層(Repository層),而其他層級中也或多或少的使用了依賴注入,在這里不過多的對于依賴注入概念上不進(jìn)行講解,如果有不了解的同學(xué),可以在微軟官網(wǎng)或者在搜索引擎搜索依賴注入相關(guān)概念,本文主要講解如何在asp.net core中實(shí)現(xiàn)自己的依賴注入容器,并且希望更多的同學(xué)能夠去閱讀源碼碼,因?yàn)樵创a中暴露的一些抽象類或者接口向開發(fā)者提供了方便開發(fā)者自定義或者拓展的口子。好了,不多啰嗦,我們開始。
First IServiceProviderFactory接口
? ? ? ?用過Autofac的同學(xué)都知道在asp.net core3版本之后,Autofac的使用方式稍微發(fā)生了一些變化,首先需要在Program.cs文件中需要使用Host.UseServiceProviderFactory方法,那實(shí)際上這個(gè)方法就是讓開發(fā)者能夠去實(shí)現(xiàn)自定義的依賴注入容器的一個(gè)拓展方法,我們可以查看一下這個(gè)方法的定義,注意看有個(gè)重點(diǎn)的接口就是IServiceProviderFactory接口,這個(gè)接口實(shí)際上是指定服務(wù)提供者的一個(gè)抽象工廠泛型接口,這是實(shí)現(xiàn)自定義IOC中最重要的接口之一,也是最開始的一步,實(shí)際上,實(shí)現(xiàn)自定義依賴注入容器,只需要實(shí)現(xiàn)兩個(gè)接口就可以實(shí)現(xiàn)自定義容器,可以看到這個(gè)方法有兩種參數(shù)機(jī)制一種是直接傳入對應(yīng)的 實(shí)現(xiàn)類,另一種是使用委托的方式去創(chuàng)建對象,并且傳入了一個(gè)HostBuilderContext的對象,我們會(huì)使用這種方式去實(shí)現(xiàn)。
Second IServiceProvider接口
? ? ? ?我們可以看到這個(gè)IServiceProviderFactory接口有兩個(gè)實(shí)現(xiàn)方法,一個(gè)是CreateBuilder方法,里面?zhèn)魅隝ServiceCollection變量,另一個(gè)方法是CreateServiceProvider方法,傳入我們這個(gè)接口指定的容器類的對象,其中IocContainer類不依賴于任何一個(gè)抽象,第一個(gè)方法的作用就是去構(gòu)造這個(gè)容器的對象,需要返回我們指定的類型的對象,即是這個(gè)類是代表著容器,存放服務(wù)的,第二個(gè)方法是將上面構(gòu)造的容器對象傳入進(jìn)來,并且返回我們指定的服務(wù)提供者,那概念很清晰了,第一個(gè)IServiceProviderFactory接口是用來指定我們的容器是哪一個(gè)類是我們的容器,以及哪一個(gè)是我們的服務(wù)提供者,那實(shí)際上的IServiceProvider就是第二個(gè)重要的一個(gè)接口了,這個(gè)接口是只有一個(gè)方法,GetService方法,參數(shù)是一個(gè)Type,代表著我們是要去獲取哪一個(gè)類型的參數(shù),返回值是Object,返回下層依賴者所需要的具體的一個(gè)對象。
Three 遵循規(guī)則實(shí)現(xiàn)自定義容器
? ? ? ? 那實(shí)際上自帶的依賴注入容器也是遵循這種規(guī)則去實(shí)現(xiàn)的,它提供了一個(gè)自帶的一個(gè)ServiceProvider的類去創(chuàng)建對象,那大家都知道啟動(dòng)一個(gè)Core的一個(gè)程序,自帶的一些依賴對象都有一百多個(gè),那大家可能會(huì)覺得,讓自己去寫這種一百多個(gè)對象的創(chuàng)建,并且類別還是core的開發(fā)者所沒有暴露出的類型,創(chuàng)建起來會(huì)很麻煩,并且還存在各種依賴,讓大家覺得可能自定義依賴注入容器可能很難,實(shí)際上,剛開始的時(shí)候我也是這么想的,表達(dá)式樹在我去年十二月份的時(shí)候就開始寫代碼了,只是今年才上傳到博客,那實(shí)際上,自定義容器我也是去年開始研究的,剛開始也是寫了很多判斷因?yàn)樗鼉?nèi)部啟動(dòng)的時(shí)候大的依賴了兩個(gè)東西一個(gè)是配置的IConfiguration,還有一個(gè)就是一個(gè)Host的一個(gè)類,下面又依賴了很多很多的類,感覺創(chuàng)建起來很麻煩,后來在想到了反射是可以獲取程序運(yùn)行時(shí)的元數(shù)據(jù)并且去構(gòu)造某個(gè)類型,那實(shí)際上,我們是可以用反射去實(shí)現(xiàn)一種投機(jī)取巧的方式去實(shí)現(xiàn)自定義依賴注入容器,那就是將啟動(dòng)所依賴服務(wù)由自帶的ServiceProvider去進(jìn)行提供和創(chuàng)建,一些項(xiàng)目開發(fā)中使用的服務(wù)由我們?nèi)ミM(jìn)行管理,那說到這,已經(jīng)有很多同學(xué)知道了怎么去進(jìn)行了,我們看代碼。
? ? ? ? ? 上圖中,我們可以看到Provider類是實(shí)現(xiàn)了IServiceProvider的接口,并且實(shí)現(xiàn)了GetService的方法,可以看到,我使用的方式是去用反射去獲取自帶的ServiceProvider的構(gòu)造函數(shù),然后創(chuàng)建這個(gè)對象,并且在GetService方法中,首先去判斷能否從自帶的Provider去獲取和創(chuàng)建對象,如果獲取不到,那說明是我們項(xiàng)目中所需要的類型,從而使用我們自定義的容器去進(jìn)行獲取對象,默認(rèn)的獲取不到是因?yàn)槲覀冊趧?chuàng)建ServiceProvider對象的時(shí)候傳入了IServiceCollection的對象,這里所包含的就是啟動(dòng)Core程序所需要的依賴的集合,這樣我們就可以保證,程序啟動(dòng)的時(shí)候是可以正常啟動(dòng)的,然后在運(yùn)行中,請求中所需要的服務(wù)類型是由我們自己去創(chuàng)建對象的,所以這樣就實(shí)現(xiàn)了簡單的IOC依賴注入容器,并且替換掉自帶的容器。
Four 控制器層的屬性注入以及拓展容器實(shí)現(xiàn)屬性注入和一接口多實(shí)現(xiàn)
? ? ? ? 按照我文章剛開始的時(shí)候所說,微軟給我們暴露了很多供我們自定義的接口和 抽象類,那如果需要在控制器層實(shí)現(xiàn)屬性注入那怎么辦呢?那實(shí)際上還有一個(gè)接口,用來讓我們?nèi)?chuàng)建控制器,那就是IControllerFactory接口,這個(gè)接口有兩個(gè)方法,一個(gè)是CreateController方法和ReleaseController方法,顧名思義就是一個(gè)是創(chuàng)建控制器,一個(gè)是銷毀控制器,那我們可以在第一個(gè)方法去實(shí)現(xiàn)控制器層的屬性注入以及一個(gè)接口多實(shí)現(xiàn)該怎么去獲取的思路,如果是屬性注入,我們是需要去創(chuàng)建一個(gè)特性用來標(biāo)記這個(gè)屬性是用來從容器中獲取對象的,我們可以在控制器層或者其他類中使用類似的方法去操作屬性注入賦值,如果是一個(gè)接口多實(shí)現(xiàn)呢,也是需要去定義兩個(gè)特性,一個(gè)特性標(biāo)記在實(shí)現(xiàn)類上面,并且構(gòu)造函數(shù)中有一個(gè)string類型的參數(shù),用來標(biāo)記是在容器中 注入的時(shí)候使用某個(gè)名稱用來標(biāo)識(shí)這個(gè)類型,其次在我們進(jìn)行獲取這個(gè)類型的時(shí)候需要在參數(shù)或者屬性用我們定義的第二個(gè)特性標(biāo)記這個(gè)參數(shù)或者屬性是從容器中獲取的是哪一個(gè)名稱哪一個(gè)類型的對象,這樣就可以實(shí)現(xiàn)一個(gè)屬性注入和一個(gè)接口多實(shí)現(xiàn)的一個(gè)操作。
?
總結(jié)
? ? ? ? 以上是我個(gè)人實(shí)現(xiàn)自定義IOC的一個(gè)解決思路,并且在net core5以及net core6中實(shí)現(xiàn),且5到6實(shí)現(xiàn)了無縫升級,沒有任何錯(cuò)誤,希望能夠?qū)Ω魑蛔x者有所幫助。還是希望眾多道友能夠多解讀源碼,去查看core框架開發(fā)者提供給我們暴露給我們的自定義拓展的一些接口和抽象類。后面我依舊會(huì)持續(xù)更新core自定義相關(guān)的東西,會(huì)包括配置還有日志等其他方面的東西,多線程方面的代碼已經(jīng)寫完,可以在QQ群6406277群文件中進(jìn)行查找,也可以查看哪個(gè)net群有叫四川觀察的,那個(gè)就是我。IL后面我也寫了很多東西,后續(xù)也會(huì)一一奉上。在此,謝謝各位看官瀏覽。
總結(jié)
以上是生活随笔為你收集整理的asp.net core自定义依赖注入容器,替换自带容器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET6 新功能和新生态
- 下一篇: WPF实现数据拾取器