前言:直接開干。
使用Autofac進行服務注冊實踐:
新建三個項目,分別是webapi項目?Wesky.Core.Autofac以及兩個類庫項目?Wesky.Core.Interface和Wesky.Core.Service。
在Webapi項目下,引用Autofac的三個包:Autofac、Autofac.Configuration和Autofac.Extensions.DependencyInjection?。
?
在類庫下,Interface用于編寫Interface接口類;Service用于開發對應的接口實現類。現在先準備了6個接口和實現,用來測試,方法實現都一樣,都是打印當前方法名稱。如圖:
?
在webapi項目下的Program類里面,添加對autofac工廠(AutofacServiceProviderFactory)的服務實現。如圖,需要先?using?Autofac.Extensions.DependencyInjection;
?
在Startup類下面,新建無返回值的方法ConfigureContainer,并且帶有一個ContainerBuilder類型的參數。然后在里面添加兩個服務的注冊,例如ServiceA和ServiceD,用來測試使用:
?
新增一個控制器TestController,并且實現一個叫Test方法的webapi,用來實驗是否依賴注入服務生效:
?
運行程序,并調用webapi,驗證依賴注入的結果:
?
Autofac依賴注入的幾個相對常見的生命周期:
1、瞬時?InstancePerDependency:每次獲取的服務實例都不一樣;
2、單例?SingleInstance:在整個容器中獲取的服務實例都是同一個;
3、作用域?InstancePerLifetimeScope:相同作用域下獲取到的服務實例相同;
4、作用域?InstancePerMatchingLifetimeScope(“作用域名稱”):可以指定到某一個具體作用域;
5、每次請求?InstancePerRequest:不同的請求獲取的服務實例不一樣;
6、隱式關系類型的嵌套作用域?InstancePerOwned:可以使用每一個擁有實例的注冊來依賴關系限定到擁有的實例。
對應注冊的方式如下代碼所示:
?
現在對這些實例的生命周期做個測試,編寫一些測試代碼,用來驗證生命周期:
?
在方法最后加個斷點,然后運行程序。
A1和?A2是瞬時周期進行注冊,每次都會產生不同的實例,所以兩個實例不一樣;
B1?和?B2是單例進行注冊,會引用同一個實例,所以兩者的實例相等;
C1和C2、C3和C4分別在兩個作用域下進行作用域注冊,所以在同一個作用域下,C1和C2、C3和C4的實例分別相等;但是C1和C3不屬于同一個作用域,所以不相等。D1/2/3/4類似,不再描述。
詳情,如圖所示:
?
Autofac通過模塊化進行注冊服務
新建一個繼承自Autofac.Module的類WeskyModule,并在里面提供Load方法的實現(在方法里面進行服務注冊),下面使用一些其他方式進行注冊,如代碼以及注釋部分:
?
在Startup類的ConfigureContainer方法下,注釋之前的注冊服務,改為引用Module模塊來進行服務注冊:
?
運行程序,在注冊ServiceE的時候會提示錯誤,這是因為上面注冊時候,排除了ServiceE所導致的,會提示服務沒注冊,如圖:
?
現在先屏蔽掉對E服務的依賴,查看注冊效果,直接在注冊以后,訪問注冊服務的Hello方法,并運行查看結果。說明服務注冊成功:
?
Autofac通過配置文件進行服務注冊的方式
Autofac也可以通過配置文件進行注冊服務,下面做個簡單的例子。
新建一個叫做autofac.json的文件,然后在里面寫上兩個簡單的單例注冊。注意:新建的json文件需要設置為始終復制,防止生成以后沒有存在根目錄里面導致的找不到文件的問題。
?
然后在WeskyModule里面,注釋掉先前的注冊,使用以下代碼進行獲取配置文件的注冊,并對A、B(B沒有在文件里面注冊,正常情況下應該是要報錯的)?和C進行測試。
?
運行程序,可以看到由于B并沒有在文件里面注冊,所以運行到服務B時候,提示未注冊服務異常:
?
由此可見,通過配置文件進行服務注冊符合預期,測試完畢。
Autofac實現AOP切面功能
先添加Autofac.Extras.DynamicProxy的包:
?
新建一個叫做WeskyAOP的類,并且繼承自,然后實現里面的Intercept方法,示例如下:
?
然后為了方便,我直接在下方新建一個IWeskyTest接口和WeskyTest類,并且提供一個Hello方法進行測試。以及對IWeskyTest添加了上面AOP的標記,如下:
?
返回WeskyModule里面,把先前注冊的內容注釋掉,然后添加對新增AOP服務的注冊,以及新增服務接口的注冊,此處注冊為一個單例,不過會行不通,不信的可以自己嘗試:
?
在Test控制器里面,添加對IWeskyTest接口服務的依賴注入,并在測試的api里面調用Hello方法進行測試。打印出AOP里面的兩句語句,代表AOP實現成功。注意,以上使用單例或者其他的進行注冊是不成功的,必須使用?EnableInterfaceInterceptors?(需要using?Autofac.Extras.DynamicProxy)
?
另外,把標記寫到實現類上也是OK的,例如:
?
Autofac通過構造函數注入
如前面內容所示,獲取實例都是通過構造函數進行。此處通過構造函數獲取實例,還有一種通過構造函數傳入IServiceProvider進行獲取。該方法可以極大減少構造函數傳入的實例過多所導致的構造函數參數臃腫。示例直接使用前篇項目做拓展,在控制器的測試api下面,直接使用。有關示例如下圖所示:
?
設置斷點,并運行程序查看效果。可見IWeskyTest接口已經被注入進來,并且可以訪問到
?
Autofac通過屬性注入方式
在ServiceA實現類里面,添加IServiceB、IServiceC的屬性。并且在ServiceA實現類里面,添加一個測試方法?Hey(),在里面對以上兩個屬性所對應的接口方法進行調用。代碼如下:
?
以及Hey需要加入到抽象類接口IServiceA:
?
對IServiceA\B\C進行服務注冊。其中,提供屬性的服務,注冊時候必須使用PropertiesAutowired方式,如下面代碼所示:
?
接著改寫控制器里面的Test方法進行測試。對應代碼以及解釋和對應的運行結果如下圖所示:
?
Autofac通過方法注入方式
改寫上面ServiceA的類為如下代碼。有關代碼說明如圖:
?
對用到的IServiceA和B進行服務注冊。如圖所示,ServiceA里面提供了方法注入,所以需要在注冊A服務的時候,使用OnActivated方法。其中,RegisterService是ServiceA服務里面提供的需要當做方法注入的方法,方法里面的IServiceB是需要被方法注入的抽象類(接口)。以下使用了瞬時,也可以使用其他的,沒有限制,包括ServiceB服務注冊時候,也可以使用非單例模式,不做限制。
?
運行程序,如果先后打印ServiceA?和?ServiceB,則代表方法注入成功。運行程序結果如下:
?
Filter過濾器里面實現支持依賴注入
先編寫一個過濾器WeskyFilter,繼承自?ActionFilterAttribute。并且在里面添加一個屬性注入的IServiceC和一個構造函數注入的IServiceD。
然后在OnActionExecuting和OnActionExecuted方法下面實現一個打印的內容,并且分別打印ServiceC實例和ServiceD實例下面的Hello方法。代碼如下:
?
對IServiceC、D進行服務注冊,以及注冊WeskyFilter過濾器,用以支持依賴注入:
?
在控制器里面的Test方法上面,添加過濾器標記,并直接運行進行結果驗證:
?
如圖所示,打印出過濾器里面的內容,并且成功訪問到了ServiceC和D的Hello方法,代表在過濾器里面實現依賴注入也是可以的。
如果覺得有幫助,歡迎轉發、在看和留言。
如果對.NET技術感興趣,或者愿意分享自己的知識,也歡迎掃碼加入我的群聊,7天內有效:
最后再次感謝大家觀看~謝謝大家。