阅读目录


一、AutoFac简单使用

 1 namespace AutofacDemo
2 {
3 class Program
4 {
5 //用于存储容器的属性
6 private static IContainer Container { get; set; }
7 static void Main(string[] args)
8 {
9 //获取容器
10 var builder = new ContainerBuilder();
11 //注册组件(类),并公开服务(接口)
12 builder.RegisterType<ConsoleOutput>().As<IOutput>();
13 builder.RegisterType<TodayWriter>().As<IDateWriter>();
14 //存储容器
15 Container = builder.Build();
16
17 WriteDate();//输出当前的日期
18 }
19 public static void WriteDate()
20 {
21 using (var scope=Container.BeginLifetimeScope())
22 {
23 //解析组件(功能类似于new一个IDateWriter的实现类)
24 var writer = scope.Resolve<IDateWriter>();
25 writer.WriteDate();
26 }
27 }
28 }
29 //输出功能接口
30 public interface IOutput
31 {
32 void Write(string content);
33 }
34 //控制台输出类
35 public class ConsoleOutput : IOutput
36 {
37 public void Write(string content)
38 {
39 Console.WriteLine(content);
40 }
41 }
42 //输出日期的接口
43 public interface IDateWriter
44 {
45 void WriteDate();
46 }
47
48 //输出今天日期的类
49 public class TodayWriter : IDateWriter
50 {
51 private IOutput _output;//输出日期的类依赖IOutput
52 public TodayWriter(IOutput output)
53 {
54 this._output = output;
55 }
56 public void WriteDate()
57 {
58 this._output.Write(DateTime.Today.ToShortDateString());
59 }
60 }
61 }

应用程序执行过程:

  “WriteDate”方法向Autofac询问IDateWriter。

  Autofac看到IDateWriter映射到TodayWriter,所以开始创建一个TodayWriter。

  Autofac认为TodayWriter在其构造函数中需要一个IOutput。

  Autofac看到IOutput映射到ConsoleOutput,所以创建一个新的ConsoleOutput实例。

  Autofac使用新的ConsoleOutput实例来完成TodayWriter的构建。

  Autofac将“WriteDate”的完全构建的TodayWriter返回给消费者。

  之后,如果您希望应用程序编写不同的日期,则可以实现不同的IDateWriter,然后在应用程序启动时更改注册。你不必改变任何其他类。 这样就实现了反转控制!


二、注册

使用Autofac 注册组件的任务是:通过创建一个ContainerBuilder并且告知builder 哪些组件公开哪些服务。

2.1 注册方式

 1  // 创建组件/服务注册的容器
2 var builder = new ContainerBuilder();
3
5 ////----------------------一、反射组件----------------////
6 // 反射组件方法1---通过类型注册
7 builder.RegisterType<ConsoleOutput>().As<IOutput>();
8 // 反射组件方法2---通过构造函数注册
9 builder.RegisterType<TodayWriter>()
10 .UsingConstructor(typeof(IOutput)).As<IDateWriter>();
11
12
13
14 ////--------------------二、实例组件----------------------////
15 // 注册创建的对象实例,把该实例作为一个服务
16 var output = new ConsoleOutput();
17 builder.RegisterInstance(output).As<IOutput>();
18 //不影响系统中原有的单例
19 builder.RegisterInstance(MySingleton.GetInstance()).ExternallyOwned();  
20
21
22
23 ////------------------三、Lambda表达式组件---------------////
24 //参数c是组件上下文(一个IComponentContext对象) ,此处该组件被创建。您可以使用它来解析来自于容器的其他组件,从而帮助你创建组件。
25
26 builder.Register(c => new TodayWriter(c.Resolve<IOutput>())).As<IDateWriter>();
27
28 //分离组件创建最大的好处就是具体类型可以变化
29 //一个组件分离的Demo:注册一个信用卡组件
30 builder.Register<CreditCard>(
31 (c, p) =>
32 {
33 var accountId = p.Named<string>("accountId");
34 if (accountId.StartsWith("9"))
35 {
36 return new GoldCard(accountId);
37 }
38 else
39 {
40 return new StandardCard(accountId);
41 }
42 });
43 //根据参数不同获取不同种类的信用卡类实例
44 var card = container.Resolve<CreditCard>(new NamedParameter("accountId", "12345"));
45
46
47 ////-------------------------四、泛型注册------------------////
48 //泛型注册,可以通过容器返回List<T> 如:List<string>,List<int>等等
49 builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)).InstancePerLifetimeScope();
50 using (IContainer container = builder.Build())
51 {
52 IList<string> ListString = container.Resolve<IList<string>>();
53 }
54
55
56 ////-----------------------五、服务与组件-------------------////
57 builder.RegisterType<ConsoleLogger>();//默认把注册类型作为公开服务
58 builder.RegisterType<ConsoleLogger>().As<ILogger>().As<IMyLogger>();//可以公开任意多个服务,但是默认的注册类型会被覆盖
59 builder.RegisterType<ConsoleLogger>().AsSelf().As<ILogger>();//加上AsSelf()默认的注册类型不会被覆盖
60 //当公开的服务重名时,服务使用的默认组件是后注册的那个
61 builder.Register<ConsoleLogger>().As<ILogger>();
62 builder.Register<FileLogger>().As<ILogger>();//默认使用后注册的FileLogger
63 //阻止该默认行为,使用builder.Register<FileLogger>().As<ILogger>().PreserveExistingDefaults(),这样不会覆盖以前注册的组件
64
65
66 ////-----------六、条件注册(IfNotRegistered,OnlyIf)-------////
67 //HandlerC不会被注册
68 builder.RegisterType<HandlerA>()
69 .AsSelf()
70 .As<IHandler>()
71 .IfNotRegistered(typeof(HandlerB));
72 builder.RegisterType<HandlerB>()
73 .AsSelf()
74 .As<IHandler>();
75 builder.RegisterType<HandlerC>()
76 .AsSelf()
77 .As<IHandler>()
78 .IfNotRegistered(typeof(HandlerB));
79
80 //只有IService和HandlerB都注册时,才会去注册Manager
81 builder.RegisterType<Manager>()
82 .As<IManager>()
83 .OnlyIf(reg =>
84 reg.IsRegistered(new TypedService(typeof(IService))) &&
85 reg.IsRegistered(new TypedService(typeof(HandlerB))));
86
87
88 // 编译容器完成注册且准备对象解析
89 Container = builder.Build();
90
91 // 现在你可以使用 Autofac 解析服务. 例如,这行将执行注册的lambda表达式对于 IConfigReader 服务.
92 using (var scope = Container.BeginLifetimeScope())
93 {
94 var writer = Container.Resolve<IOutput>();
95 var dataWriter = Container.Resolve<IDateWriter>();
96 writer.Write("111");//输出111
97 dataWriter.WriteDate();//输出当前日期
98 Console.ReadKey();
99 }

2.2 带参数注册

1、参数类型

  Autofac支持的参数类型有三种:

    NamedParameter - 通过名称匹配目标参数

    TypedParameter - 通过类型匹配目标参数(需要精确匹配类型)

    ResolvedParameter - 灵活的参数匹配

例子:一个读取配置文件的类,构造器需要传入参数:节点名称

1 public class ConfigReader : IConfigReader
2 {
3 public ConfigReader(string configSectionName)
4 {
5 // 存储配置的节点名称
6 }
7
8 // ...读取基于节点名称的配置
9 }

2、反射组件参数

Parameters with Reflection Components----注册时传入

 1 // 使用一个命名参数:
2 builder.RegisterType<ConfigReader>()
3 .As<IConfigReader>()
4 .WithParameter("configSectionName", "mySectionName");
5
6 // 使用一个类型参数:
7 builder.RegisterType<ConfigReader>()
8 .As<IConfigReader>()
9 .WithParameter(new TypedParameter(typeof(string), "mySectionName"));
10
11 // 使用一个解析参数:
12 builder.RegisterType<ConfigReader>()
13 .As<IConfigReader>()
14 .WithParameter(
15 new ResolvedParameter(
16 (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "configSectionName",
17 (pi, ctx) => "mySectionName"));

3、Lambda表达式组件参数

Parameters with Lambda Expression Components----解析时传入

  在组件注册表达式中,你可以通过改变委托签名使用传入参数进行注册,代替仅仅接收一个IComponentContext参数,一个IComponentContext 和 IEnumerable<Parameter>参数:
1 builder.Register((c, p) =>
2 new ConfigReader(p.Named<string>("configSectionName")))
3 .As<IConfigReader>();

当你解析参数时,你的lambda将使用这些参数来传入值:

 var reader = scope.Resolve<IConfigReader>(new NamedParameter("configSectionName", "mySectionName"));

参考文章:

  1、https://blog.csdn.net/chiyueqi/article/details/52446569

  2、http://www.yuanjiaocheng.net/Autofac/register-parameters.html

IoC之AutoFac(一)——简单使用和组件注册的更多相关文章

  1. Autofac使用代码方式进行组件注册【不需要依赖】

    public class AutofacFactory2     {         IBank bank;         public AutofacFactory2()         {    ...

  2. Ioc容器Autofac系列(3)-- 三种注册组件的方式

    简单来说,所谓注册组件,就是注册类并映射为接口,然后根据接口获取对应类,Autofac将被注册的类称为组件. 虽然可像上篇提到的一次性注册程序集中所有类,但AutoFac使用最多的还是单个注册.这种注 ...

  3. [转]ASP.NET MVC IOC 之AutoFac攻略

    本文转自:http://www.cnblogs.com/WeiGe/p/3871451.html 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用A ...

  4. ASP.NET MVC IOC 之AutoFac攻略

    一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天,发现这个东东确实是个高大上的IOC容器~ Autofa ...

  5. ASP.NET MVC IOC 之AutoFac

    ASP.NET MVC IOC 之AutoFac攻略 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天, ...

  6. ASP.NET IOC之 AutoFac的认识和结合MVC的使用

    这几天研究了解发现AutoFac是个牛X的IOC容器,是.NET领域比较流行的IOC框架之一,传说是速度最快的,~ 据相关资料,相关学习,和认知,遂做了一些整理 优点: 它是C#语言联系很紧密,也就是 ...

  7. 关于.NET中的控制反转及AutoFac的简单说明

    目录 1.控制反转 1.1 什么是依赖? 1.2 什么是控制反转? 1.3 什么是依赖注入? 1.4 简单总结 2.控制反转容器 2.1 IOC容器说明 2.2 使用AutoFac的简介示例 3 使用 ...

  8. IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用

    Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...

  9. Ioc容器Autofac系列(1)-- 初窥

     一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...

随机推荐

  1. Java 之 CSS

    1.CSS a.定义:CSS 指层叠样式表 b.意义:为了解决内容与表现分离的问题 c.特点:多个样式可层叠为一 2.用法: a.行内样式:style <span style="col ...

  2. 多个SDK控制管理

    需求:制作一个公共组件,可以实现多个SDK想用哪个用哪个,集中管理 组织方式: 架构形式 注意点: 1.sdk必须通过maven库来compile,因为jar会打到aar中:所以library和主mo ...

  3. 从函数式编程到Ramda函数库(二)

    Ramda 基本的数据结构都是原生 JavaScript 对象,我们常用的集合是 JavaScript 的数组.Ramda 还保留了许多其他原生 JavaScript 特性,例如,函数是具有属性的对象 ...

  4. SpringBoot+Mybatis+MySql学习

    介绍一下SpringBoot整合mybatis,数据库选用的是mysql. 首先创建数据库 CREATE DATABASE test; 建表以及插入初始数据(sql是从navicat中导出的) SET ...

  5. sql的简单操作

    mysql 一.mysql简介和安装 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应 ...

  6. c# 获取键盘的输入

    c# 获取键盘的输入   Console 类公开了三个方法获取键盘的输入,分别是Read .Readkey.ReadLine Read方法: 每次只能读入一个字符,如果没有字符可以读,返回-1,Rea ...

  7. Kotlin基础(二)函数的定义与调用

    函数的定义与调用 一.预备知识:在Kotlin中创建集合 fun main(args: Array<String>) { //Kotlin中定义各自集合 val ,,,) val list ...

  8. 如何使用TDD和React Testing Library构建健壮的React应用程序

    如何使用TDD和React Testing Library构建健壮的React应用程序 当我开始学习React时,我努力的一件事就是以一种既有用又直观的方式来测试我的web应用程序. 每次我想测试它时 ...

  9. CentOS7.5 通过wget下载文件到指定目录

    在Linux命令行下面下载文件,通过wget是比较普遍简单的,比如在CentOS7 里面也一样. 我们先来看下自己的CentOS7 系统有没有安装wget: [root@test redis]# rp ...

  10. BZOJ1897 : tank 坦克游戏

    设$f[i][j][k]$表示坦克位于$(i,j)$,目前打了不超过$k$个位置的最大得分. 初始值$f[1][1][k]$为在$(1,1)$射程内最大$k$个位置的分数总和. 对于每次移动,会新增一 ...