IoC之AutoFac(一)——简单使用和组件注册
阅读目录
一、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(一)——简单使用和组件注册的更多相关文章
- Autofac使用代码方式进行组件注册【不需要依赖】
public class AutofacFactory2 { IBank bank; public AutofacFactory2() { ...
- Ioc容器Autofac系列(3)-- 三种注册组件的方式
简单来说,所谓注册组件,就是注册类并映射为接口,然后根据接口获取对应类,Autofac将被注册的类称为组件. 虽然可像上篇提到的一次性注册程序集中所有类,但AutoFac使用最多的还是单个注册.这种注 ...
- [转]ASP.NET MVC IOC 之AutoFac攻略
本文转自:http://www.cnblogs.com/WeiGe/p/3871451.html 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用A ...
- ASP.NET MVC IOC 之AutoFac攻略
一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天,发现这个东东确实是个高大上的IOC容器~ Autofa ...
- ASP.NET MVC IOC 之AutoFac
ASP.NET MVC IOC 之AutoFac攻略 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天, ...
- ASP.NET IOC之 AutoFac的认识和结合MVC的使用
这几天研究了解发现AutoFac是个牛X的IOC容器,是.NET领域比较流行的IOC框架之一,传说是速度最快的,~ 据相关资料,相关学习,和认知,遂做了一些整理 优点: 它是C#语言联系很紧密,也就是 ...
- 关于.NET中的控制反转及AutoFac的简单说明
目录 1.控制反转 1.1 什么是依赖? 1.2 什么是控制反转? 1.3 什么是依赖注入? 1.4 简单总结 2.控制反转容器 2.1 IOC容器说明 2.2 使用AutoFac的简介示例 3 使用 ...
- IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用
Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...
- Ioc容器Autofac系列(1)-- 初窥
一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...
随机推荐
- Flume的四个使用案例
一.Flume监听端口 1,在linux机器上下载telnet工具 yum search telnet yumm install telnet.x86_64 2.编写flume的配置文件,并将文件复制 ...
- 开源医学图像处理平台NiftyNet介绍
18年下半年10月份左右,老师分配有关NiftyNet平台的相关学习的任务,时隔5个月,决定整理一下以前的笔记,写成相应的博客! 目录 1.NiftyNet平台简介 2.NiftyNet平台架构设计 ...
- 安排~~炒鸡全的JS兼容问题,码上-----【XUEBIG】
如何处理兼容问题 如果两个都是属性,用逻辑||做兼容 如果有一个是方法,用三元做兼容 如果是多个属性或方法,封装函数做兼容 两个小知识点: 1.取消拖拽的默认行为: document.ondragst ...
- Java 的Event机制浅析
https://blog.csdn.net/kehyuanyu/article/details/23540901
- Jenkins部署码云SpringBoot项目到远程服务器
本文是上一篇文章的后续,上一篇只是利用Jenkins部署项目到本地,并启动,本文是将项目部署到远程服务器并执行. 1.环境准备 1.1 安装插件 上一篇文章已经介绍了需要安装的应用及插件,这一篇还需要 ...
- BZOJ.1535.[POI2005]SZA-Template(KMP DP)
BZOJ 洛谷 \(Description\) 给定一个字符串\(s\),求一个最短的字符串\(t\)满足,将\(t\)拼接多次后,可以得到\(s\).拼接是指,可以将\(t\)放在当前串的任意位置, ...
- BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)
BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...
- luffy项目的接口开发
处理跨域请求 主要的思路: 设置一个基于CORS的中间件来处理,关于跨域的产生与处理手段 settings.py: MIDDLEWARE = [ 'django.middleware.security ...
- 潭州课堂25班:Ph201805201 django 项目 第四十六课 查错 补缺 (课堂笔记
从讲项目开始,查找错误,完善笔记,尽可能 翻译没一句代码(以后台为主), 本项目亮点,也是重点 Django ORM中对数据查询的优化(only.defer.select_related) redis ...
- Java 构造器 考虑用静态构造方法代替构造器
类可以提供一个公有的静态工厂方法,它是一个返回类的实例的静态方法.静态工厂方法与设计模式中的工厂方法模式不同. 优势: 静态工厂方法与构造器不同的第一大优势在于,它们有名称.一个类只能有一个带有指定签 ...