C#实现乞丐版IOC容器
一、前言
netcore中的容器非常好用,今天我們自己來簡單實現一個。
實現容器的核心接口有兩個:IServiceCollection、IServiceProvider。其中IServiceCollection定義容器集合,IServiceProvider提供容器中對象的訪問。話不多說,直接編碼。
二、IServiceCollection
首先我們得定義IServiceCollection接口,這個接口主要用以幫我們實現自定義集合,所以我們選擇繼承IList。代碼如下:
細心你肯定發現了IList中ServiceDescriptor的定義了,這個類其實就是一個服務的描述類,我們F12進去看一下是怎么定義的。代碼如下:
真的就是非常簡單,ServiceType和ImplServiceType分別定義接口和實現類,LifeTime是一個枚舉,用來定義這個類型的生命周期。代碼如下:
現在我們已經定義好了IServiceCollection,下面就定義它的實現類:ServiceCollection,這個類就是具體的維護一個ServiceDescriptor集合。代碼如下:
你也看到了,這個類,真的太簡單了,就是用來將服務添加到集合_descriptors中了。唉,簡單到不想多說了。寫到這里,乞丐版容器其實已經實現了,我們來弄個控制臺試下。代碼如下:
細心的你可能會問,工作中使用容器的時候好像都是用的AddSingleton、AddScope的方法注入的,其實這些都是對IServiceCollection的擴展方法。那我們也來弄一個吧,先定義一個擴展類:ServiceCollectionExtensions。代碼如下:
寫好這些擴展方法后,我們再來改下控制臺中的代碼,就和你實際工作中長一樣了。代碼如下:
三、IServiceProvider
這時你可能又會問,服務我已經注冊到容器了,我要怎么使用呢?這個時候我們就要用到開頭所說的IServiceProvider,這個接口定義訪問容器中的服務,記住繼承下IDispose,用來釋放資源。代碼如下:
定義好接口以后,我們就要弄一個實現類,即ServiceProvider,這個類中主要實現GetService方法,用來提供服務對象實例。代碼如下:
ServiceProvider構造方法需要IServiceCollection對象,不然它都不知道提供哪個容器的服務對象。這個類中維護了一個_objects字典,用來管理單例(Singleton)、范圍(Scoped)對象。GetService方法也非常的簡單,先到容器對象中找下已注冊的服務,如果找不到,直接返回null。如果找到,則根據這個注冊類型的生命周期返回對象:瞬時對象的話每次都創建新對象,單例和范圍對象的話先到_objects查詢,如果有的話直接返回,沒有的話重新創建一個,放回_objects后再返回。有了ServiceProvider類后,我們就可以在控制臺中提供注冊的服務對象了。代碼如下:
上面的代碼中,我們new了一個ServiceProvider對象,并把ServiceCollection對象傳給了它,意思是我把容器交給你,訪問服務對象的事就拜托你了。然后我們通過GetService得到幾個單例和瞬時對象,我們運行下看下,他們hashcode是不是和我們預期的一樣。代碼如下:
我們發現得到的單例對象hashcode值都一樣,瞬時對象每次都不一樣,說明我們這個IOC基本功能已經實現了,真了不起。上面的new ServiceProvider我們也可以改成擴展方法。代碼如下:
然后我們測試代碼中替換一下。代碼如下:
細心的你肯定又發現不對,你這一直沒講Scope呀。其實Scope和Singleton是一樣的,Scope只是一定范圍的單例。你只要在范圍內每次new一個ServiceProvider就行了。代碼如下:
四、總結
至此,我們乞丐版的IOC容器就完成了,能力有限,只是實現最簡單的功能,很多校驗都沒有寫。還是建議大家直接看微軟的源碼,那個里面寫的比較高端,我這只是毛毛雨,如果能幫到你一點點,我就會很開心了,哈哈。
總結
以上是生活随笔為你收集整理的C#实现乞丐版IOC容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: T-SQL | 逻辑查询处理内幕学习
- 下一篇: C#9引入的自定义类型record