Autofac实现有条件的DI
Autofac.Annotation框架是我用.netcore寫的一個DI框架,基于Autofac參考 Spring注解方式所有容器的注冊和裝配,切面,攔截器等都是依賴標簽來完成。
開源地址:https://github.com/yuzd/Autofac.Annotation
本期講的是最新實現的功能
有條件的DI
有些時候我們想要滿足xxx條件才把一個類注冊到容器里面。比如如何切換Services,如果是Spring,可以根據條件注冊Bean和Configuration。所以我參考Spring的條件注解也在我的Autofac.Annotation框架中也實現了以下注解:
| Conditional | 打在class或者方法上面 | 條件加載,自定義實現的 |
| ConditionOnBean | 打在標有Bean注解的方法上面 | 條件加載 |
| ConditionOnMissingBean | 打在標有Bean注解的方法上面 | 條件加載 |
| ConditionOnClass | 打在class或者方法上面 | 條件加載 |
| ConditionOnMissingClass | 打在class或者方法上面 | 條件加載 |
| ConditionOnProperty | 打在class或者方法上面 | 條件加載 |
| ConditionOnProperties | 打在class或者方法上面 | 條件加載 |
| DependsOn | 可以配合Bean和Component使用 | A的實例化依賴另一個B的實例化,但是A并不需要持有一個B的對象 |
下面來講講使用方法:
ConditionOnBean和ConditionOnMissingBean
這2個注解是只能配合Bean注解一起使用,且只能打在方法上面,不能打在class上面
ConditionOnBean的意思是,如果指定的類已經被注冊的話,我才要注冊。
上面的代碼的意思是,如果Test10Model3被注冊的話,才會注冊Test10Model5
ConditionOnMissingBean的意思是,如果指定的類沒被注冊的話,我才要注冊。
上面的代碼的意思是,如果Test10Model1沒被注冊的話,才會注冊Test10Model3
ConditionOnClass和ConditionOnMissingClass
這2個注解是配合Compoment或者AutoConfiguration,PointCut等注解一起使用,可以打在class和method上面,該注解的參數需要填入類的完整名稱
ConditionOnClass的意思是如果當前運行環境存在指定的類的話,就注冊
ConditionOnMissingClass的意思是如果當前運行環境不存在指定的類的話,就注冊
ConditionOnProperty和ConditionOnProperties
這2個注解可以配合Bean,Compoment,AutoConfiguration,PointCut等注解一起使用,可以打在class和method上面
意思是,如果數據源(讀取當前項目的appsettings.json)
指定的key對應的值為xxx時
或者不存在指定的key
就注冊
appsettings.json
{"onproperty":?"on" }里面存在指定的key為xxx時就注冊
或者不存在指定的key
當想要指定多個值同時滿足的話就用ConditionOnProperties,道理是一樣的~!
Conditional
這個注解接受一個實現了ICondition接口的Type類型的參數。具體的判斷條件由自己實現(比如上面的幾個條件注解都滿足不了你,那你就用這個注解搭配自定義的條件)
首先我們定義一個class實現ICondition接口的ShouldSkip方法,下面的類的意思看注釋應該可以明白:
public?class?Test10Condition?:?ICondition {///?<summary>///?只有當?windows?系統下才被注冊///?</summary>///?<param?name="context"></param>///?<param?name="metadata"></param>///?<returns>返回true代表不滿足條件,那就不會被注冊到容器</returns>public?bool?ShouldSkip(IComponentRegistryBuilder?context,?object?metadata){if?(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)){//是linux系統?就不注冊return?true;}if?(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)){//是mac系統?也不注冊return?true;}//是windows系統?那就注冊return?false;} }下面我們來使用上面的條件用Conditional注解打在方法上面,這個條件表明了只有在windows平臺才會將Test10Model1注冊到容器中
[AutoConfiguration] public?class?Test10Config {[Bean][Conditional(typeof(Test10Condition))]public?Test10Model1?getTest10Model1(){Console.WriteLine("registered?Test10Model1");return?new?Test10Model1();}}上面的例子是結合Bean注解一起使用,Conditional注解還可以打在class上面,結合Compoment或者AutoConfiguration注解來實現滿足條件才注冊!
Conditional也是上面幾個其他注解的父類
image不同的是上面幾個其他注解的構造方法都指定了自己默認的實現類。
這樣面向接口設計的好處是在注冊的初始化階段針對驗證條件的邏輯就可以統一處理:只搜集 Conditional或者Conditional的子類注解,且約束了條件判斷的類統一得實現ICondition接口。
DependsOn
該注解可以配合Bean和Component注解一起使用,和ConditionXXX系列不一樣,是用來表示一個 A的實例化依賴另一個B的實例化, 但是A并不需要持有一個B的對象
[Bean] [DependsOn(typeof(Test12Bean4))] public?Test12Bean3?get13() {Debug.WriteLine("new?Test12Bean3");return?new?Test12Bean3?{?Hello?=?"world"?}; }[Bean] public?Test12Bean4?get14() {Debug.WriteLine("new?Test12Bean4");result.Add("get14");return?new?Test12Bean4?{?Hello?=?"world"?}; }上面的意思是在需要加載Test12Bean3實例(還沒)的時候,由于設置了DependsOn類Test12Bean4,先去加載Test12Bean4
[Component] [DependsOn(typeof(Test12Bean8))] public?class?Test12Bean7 {public?Test12Bean7(){//Console.WriteLine("然后我在加載")?}public?string?Hello?{?get;?set;?} }[Component] public?class?Test12Bean8 {public?Test12Bean8(){//Console.WriteLine("我先加載")}public?string?Hello?{?get;?set;?} }上面的意思是在需要加載Test12Bean7的實例的時候,先去加載Test12Bean8
好了,有條件的DI介紹到此,更多教程請參考項目wiki(教程很詳細哦,別忘記給個star)
https://github.com/yuzd/Autofac.Annotation/wiki
我是正東,學的越多不知道也越多。寫代碼的樂趣在于你可以展現你發現的美。
總結
以上是生活随笔為你收集整理的Autofac实现有条件的DI的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 备份恢复与同步(数据搬运专家)
- 下一篇: 如何计算 string 的 crc32