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的意思是,如果指定的类已经被注册的话,我才要注册。
[AutoConfiguration]
public class Test10Config
{
[Bean]
[ConditionOnBean(typeof(Test10Model3))]
public Test10Model5 getTest10Model5()
{
Console.WriteLine("registered Test10Model5");
return new Test10Model5();
}
}
上面的代码的意思是,如果Test10Model3被注册的话,才会注册Test10Model5
ConditionOnMissingBean的意思是,如果指定的类没被注册的话,我才要注册。
[AutoConfiguration]
public class Test10Config
{
[Bean]
[ConditionOnMissingBean(typeof(Test10Model1))]
public Test10Model3 getTest10Model3()
{
Console.WriteLine("registered Test10Model3");
return new Test10Model3();
}
}
上面的代码的意思是,如果Test10Model1没被注册的话,才会注册Test10Model3
ConditionOnClass和ConditionOnMissingClass
这2个注解是配合Compoment或者AutoConfiguration,PointCut等注解一起使用,可以打在class和method上面,该注解的参数需要填入类的完整名称
ConditionOnClass的意思是如果当前运行环境存在指定的类的话,就注册
[Bean]
[ConditionOnClass("Autofac.Annotation.Test.Test10Model2,Autofac.Configuration.Test")]
public Test10Model6 getTest10Model6()
{
//找的到class 所以可以注册Test10Model6
Console.WriteLine("registered Test10Model6");
return new Test10Model6();
}
ConditionOnMissingClass的意思是如果当前运行环境不存在指定的类的话,就注册
[Bean]
[ConditionOnMissingClass("Autofac.Annotation.Test.test10.Test10Model2,xxxx")]
public Test10Model7 getTest10Model7()
{
//找不到class 所以注册Test10Model7
Console.WriteLine("registered Test10Model7");
return new Test10Model7();
}
ConditionOnProperty和ConditionOnProperties
这2个注解可以配合Bean,Compoment,AutoConfiguration,PointCut等注解一起使用,可以打在class和method上面
意思是,如果数据源(读取当前项目的appsettings.json)
指定的key对应的值为xxx时 或者不存在指定的key
就注册
appsettings.json
{
"onproperty": "on"
}
里面存在指定的key为xxx时就注册
[Bean]
[ConditionalOnProperty("onproperty", "on")]
public Test10Model8 getTest10Model8()
{
//因为配置文件onproperty的值为on 所以会注册
Console.WriteLine("registered Test10Model8");
return new Test10Model8();
}
或者不存在指定的key
[Bean]
[ConditionalOnProperty("onproperty1", matchIfMissing = true)]
public Test10Model10 getTest10Model10()
{
//由于配置文件里面没有onproperty1 所以会注册
Console.WriteLine("registered Test10Model10");
return new Test10Model10();
}
当想要指定多个值同时满足的话就用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也是上面几个其他注解的父类
不同的是上面几个其他注解的构造方法都指定了自己默认的实现类。
这样面向设计的好处是在注册的初始化阶段针对验证条件的逻辑就可以统一处理:只搜集 Conditional或者Conditional的子类注解,且约束了条件判断的类统一得实现ICondition接口。
DependsOn
该注解可以配合Bean和Component注解一起使用,是用来表示一个 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的更多相关文章
- 浅谈.Net Core中使用Autofac替换自带的DI容器
为什么叫 浅谈 呢?就是字面上的意思,讲得比较浅,又不是不能用(这样是不对的)!!! Aufofac大家都不陌生了,说是.Net生态下最优秀的IOC框架那是一点都过分.用的人多了,使用教程也十分丰富, ...
- NET Core 3.0 新姿势 将AutoFac替换内置DI
.NET Core 3.0 和 以往版本不同,替换AutoFac服务的方式有了一定的变化,在尝试着升级项目的时候出现了一些问题. 原来在NET Core 2.1时候,AutoFac返回一个 IServ ...
- NET Core 3.0 AutoFac替换内置DI的新姿势
原文:NET Core 3.0 AutoFac替换内置DI的新姿势 .NET Core 3.0 和 以往版本不同,替换AutoFac服务的方式有了一定的变化,在尝试着升级项目的时候出现了一些问题. 原 ...
- Autofac QuickStart
1 构建应用程序 示例: 我们期望有一个输出工具类,当前希望通过控制台(console)输出,但是又希望仅能在控制台模式下输出.所以我们把输出抽象为一个接口 using System; namespa ...
- ASP.NET Core 3.0 原生DI拓展实现IocManager
昨天.NET Core 3.0 正式发布,创建一个项目运行后发现:原来使用的Autofac在ConfigureServices返回IServiceProvider的这种写法已经不再支持.当然Autof ...
- 把Autofac玩的和javaSpring一样6
大家好,今天来介绍我开源的一个autofac.Annotation项目 源码:https://github.com/yuzd/Autofac.Annotation 本项目是autofa的一个扩展组件, ...
- Lind.DDD.IoC(大叔推荐)~在服务定位器中引入IoC容器~容器的适配器
回到目录 关于依赖倒置(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口,通俗的讲,就是高层模块定义接口,低层模块负责实现,这在我们实际开发中经常被用到,层与层之间引用,经 ...
- 老司机学新平台 - Xamarin Forms开发框架二探 (Prism vs MvvmCross)
在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现在也支持Xamarin Forms了, ...
- Prism vs MvvmCross
Prism vs MvvmCross 在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现 ...
随机推荐
- Python——连接数据库操作
一.数据库基础用法 要先配置环境变量,然后cmd安装:pip install pymysql 1.连接MySQL,并创建wzg库 #引入decimal模块 import pymysql #连接数据库 ...
- RocketMQ源码详解 | Broker篇 · 其五:高可用之主从架构
概述 对于一个消息中间件来讲,高可用功能是极其重要的,RocketMQ 当然也具有其对应的高可用方案. 在 RocketMQ 中,有主从架构和 Dledger 两种高可用方案: 第一种通过主 Brok ...
- [BUUCTF]PWN——jarvisoj_fm
jarvisoj_fm 附件 步骤: 例行检查,32位,开启了canary和nx保护 运行一下程序,看看大概的情况 32位ida载入,shift+f12检索程序里的字符串,看见了 " /bi ...
- 【论文笔记】 Denoising Implicit Feedback for Recommendation
Denoising Implicit Feedback for Recommendation Authors: 王文杰,冯福利,何向南,聂礼强,蔡达成 WSDM'21 新加坡国立大学,中国科学技术大学 ...
- JavaFx WebView使用研究
原文: JavaFx WebView使用研究 | Stars-One的杂货小窝 本篇是基于TornadoFx框架的基础研究的,示例代码都是Kotlin版本,各位可以看着参考下 WebView中比较重要 ...
- .NET6中一些常用组件的配置及使用记录,持续更新中。。。
NET6App 介绍 .NET 6的CoreApp框架,用来学习.NET6的一些变动和新特性,使用EFCore,等一系列组件的运用,每个用单独的文档篇章记录,持续更新文档哦. 如果对您有帮助,点击右上 ...
- CF916A Jamie and Alarm Snooze 题解
Content 令一个时间为幸运时间,当且仅当该时间中包含数字 \(7\). 小 J 很懒,他决定在 \(h\) 时 \(m\) 分起床,于是他将闹钟设定在一个很幸运的时间,并通过按一次按钮以多睡 \ ...
- java 图形化工具Swing 监听键盘输入字符触发动作getInputMap();getActionMap();
双缓冲技术的介绍: 所有的Swing组件默认启用双缓冲绘图技术.使用双缓冲技术能改进频繁重绘GUI组件的显示效果(避免闪烁现象)JComponent组件默认启用双缓冲,无须自己实现双缓冲.如果想关闭双 ...
- mvn 把本地jar包打包到本地仓库中
命令如下: mvn install:install-file -Dfile=apache-ant-zip-2.3.jar -DgroupId=com.ckfinder -DartifactId=apa ...
- libevent源码学习(2):内存管理
目录 内存管理函数 函数声明 event-config.h 函数定义 event_mm_malloc_ event_mm_calloc_ event_mm_strdup_ event_mm_reall ...