阅读目录


一、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. hdu 3078 Network (暴力)+【LCA】

    <题目链接> 题目大意:给定一颗带点权的树,进行两种操作,k=0,更改某一点的点权,k!=0,输出a~b路径之间权值第k大的点的点权. 解题分析:先通过RMQ的初始化,预处理pre[]数组 ...

  2. CMake结合Visual Studio中开发Qt应用程序注意事项

    Qt工程管理 个人比较偏爱于使用CMake来管理C++工程,因为只要编写一个CMakeLists.txt文件,就可以在Windows和Mac上生成各自的IDE工程.在Windows上, CMake自然 ...

  3. 路由网关---zuul

    Zuul:Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架.Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门. 在微服务盛行的时代,客户端与系统之 ...

  4. 向量图兼容组件VectorCompat

    向量图兼容组件VectorCompat Android从5.0(API Level 21)开始,支持矢量图和动画矢量图.采用这两种图,可以避免传统图片因为缩放而产生失真.VectorCompat组件是 ...

  5. 157. [USACO Nov07] 奶牛跨栏

    157. [USACO Nov07] 奶牛跨栏(点击转到COGS) 输入文件:hurdles.in   输出文件:hurdles.out 时间限制:1 s   内存限制:128 MB 译 by CmY ...

  6. 潭州课堂25班:Ph201805201 django 项目 第二十九课 docker实例,文件下载前后台实现 (课堂笔记)

    docker 实例 :wq!保存退出 放入一个 html 文件 权限不够,加 sudo 查看本地仓库的 image 运行 docker -- name,后跟个运行名, -p 物理机端口映射到容器端口, ...

  7. Django复习1

    django常用命令:http://www.cnblogs.com/ldq1996/p/7731930.html Django查询SQL语句: http://www.cnblogs.com/ldq19 ...

  8. python正则表达式(三)

    表示边界 示例1:$ 需求:匹配163.com的邮箱地址 #coding=utf-8 import re # 正确的地址 ret = re.match("[\w]{4,20}@163\.co ...

  9. BZOJ2243[SDOI2011]染色——树链剖分+线段树

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...

  10. nodeJs --- web服务器创建

    一.下载nodeJs http://nodejs.cn/download/ 根据自己的情况选择下载 然后在命令行中输入 node -v 看是否安装成功 (下载node时,会把npm包处理工具一起下) ...