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上面

  1. ConditionOnBean的意思是,如果指定的类已经被注册的话,我才要注册。

[AutoConfiguration]
public class Test10Config
{
    [Bean]
    [ConditionOnBean(typeof(Test10Model3))]
    public Test10Model5 getTest10Model5()
    {
        Console.WriteLine("registered Test10Model5");
        return new Test10Model5();
    }
    
}

上面的代码的意思是,如果Test10Model3被注册的话,才会注册Test10Model5

  1. 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上面,该注解的参数需要填入类的完整名称

  1. ConditionOnClass的意思是如果当前运行环境存在指定的类的话,就注册

[Bean]
[ConditionOnClass("Autofac.Annotation.Test.Test10Model2,Autofac.Configuration.Test")]
public Test10Model6 getTest10Model6()
{
    //找的到class 所以可以注册Test10Model6
    Console.WriteLine("registered Test10Model6");
    return new Test10Model6();
}
  1. 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"
}
  1. 里面存在指定的key为xxx时就注册

[Bean]
[ConditionalOnProperty("onproperty", "on")]
public Test10Model8 getTest10Model8()
{
    //因为配置文件onproperty的值为on 所以会注册
    Console.WriteLine("registered Test10Model8");
    return new Test10Model8();
}
  1. 或者不存在指定的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也是上面几个其他注解的父类

image

不同的是上面几个其他注解的构造方法都指定了自己默认的实现类。

这样面向设计的好处是在注册的初始化阶段针对验证条件的逻辑就可以统一处理:只搜集 Conditional或者Conditional的子类注解,且约束了条件判断的类统一得实现ICondition接口。

image

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的更多相关文章

  1. 浅谈.Net Core中使用Autofac替换自带的DI容器

    为什么叫 浅谈 呢?就是字面上的意思,讲得比较浅,又不是不能用(这样是不对的)!!! Aufofac大家都不陌生了,说是.Net生态下最优秀的IOC框架那是一点都过分.用的人多了,使用教程也十分丰富, ...

  2. NET Core 3.0 新姿势 将AutoFac替换内置DI

    .NET Core 3.0 和 以往版本不同,替换AutoFac服务的方式有了一定的变化,在尝试着升级项目的时候出现了一些问题. 原来在NET Core 2.1时候,AutoFac返回一个 IServ ...

  3. NET Core 3.0 AutoFac替换内置DI的新姿势

    原文:NET Core 3.0 AutoFac替换内置DI的新姿势 .NET Core 3.0 和 以往版本不同,替换AutoFac服务的方式有了一定的变化,在尝试着升级项目的时候出现了一些问题. 原 ...

  4. Autofac QuickStart

    1 构建应用程序 示例: 我们期望有一个输出工具类,当前希望通过控制台(console)输出,但是又希望仅能在控制台模式下输出.所以我们把输出抽象为一个接口 using System; namespa ...

  5. ASP.NET Core 3.0 原生DI拓展实现IocManager

    昨天.NET Core 3.0 正式发布,创建一个项目运行后发现:原来使用的Autofac在ConfigureServices返回IServiceProvider的这种写法已经不再支持.当然Autof ...

  6. 把Autofac玩的和javaSpring一样6

    大家好,今天来介绍我开源的一个autofac.Annotation项目 源码:https://github.com/yuzd/Autofac.Annotation 本项目是autofa的一个扩展组件, ...

  7. Lind.DDD.IoC(大叔推荐)~在服务定位器中引入IoC容器~容器的适配器

    回到目录 关于依赖倒置(DIP) 高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口,通俗的讲,就是高层模块定义接口,低层模块负责实现,这在我们实际开发中经常被用到,层与层之间引用,经 ...

  8. 老司机学新平台 - Xamarin Forms开发框架二探 (Prism vs MvvmCross)

    在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现在也支持Xamarin Forms了, ...

  9. Prism vs MvvmCross

    Prism vs MvvmCross 在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现 ...

随机推荐

  1. Netty 编解码奥秘

    Netty中编解码 Netty 的解码器有很多种,比如基于长度的,基于分割符的,私有协议的.但是,总体的思路都是一致的. 拆包思路:当数据满足了 解码条件时,将其拆开.放到数组.然后发送到业务 han ...

  2. MySQL记录锁、间隙锁、临键锁小案例演示

    生成间隙(gap)锁.临键(next-key)锁的前提条件 是在 RR 隔离级别下. 有关Mysql记录锁.间隙(gap)锁.临键锁(next-key)锁的一些理论知识之前有写过,详细内容可以看这篇文 ...

  3. Nginx配置访问黑名单

    目录 一.简介 二.脚本 一.简介 有的时候需要将某些大访问量的ip加入到黑名单中 二.脚本 1.脚本内容为,检测本地并发访问超过15并且是ip地址,则加入nginx黑名单中.其中的53a是deny行 ...

  4. HMAC在“挑战/响应”(Challenge/Response)身份认证的应用

    HMAC的一个典型应用是用在"挑战/响应"(Challenge/Response)身份认证中. 认证流程 (1) 先由客户端向服务器发出一个验证请求. (2) 服务器接到此请求后生 ...

  5. Decorator 模式转载

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://tianli.blog.51cto.com/190322/35287 摘要:本文深 ...

  6. 主流微服务一站式解决方案Spring Cloud Alibaba入门看这篇就足够了

    学习路线 **本人博客网站 **IT小神 www.itxiaoshen.com 生态概述 架构演进 什么是微服务 https://martinfowler.com/microservices/ Mic ...

  7. Mysql 主从复制机制

    https://blog.csdn.net/girlgolden/article/details/89226528 MySQL异步复制及semi-sync半同步复制,它们都基于MySQL binlog ...

  8. mail如何在linux中发送邮件,使用163邮箱发信。

    如何在linux中发送邮件,使用163邮箱发信.   linux中,可以使用mail命令往外发送邮件,在使用前,只需要指定如下简单配置即可,这里演示用  163.com    邮箱发送至 qq.com ...

  9. mysql添加上log_bin步骤如下

    mysql添加上log_bin步骤如下

  10. uniapp+nvue实现仿微信/得物相册插件:选择界面 +自定义相册+图片视频过滤

    本篇文章基于uniapp 框架+ nvue,实现了uniapp仿微信/得物相册选择功能实例项目,该插件实例实现了以下功能: 1: 相册过滤 2: 图视频过滤 3: 界面UI定制化 4: 栅格列数定制化 ...