阅读目录


一、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集合—Set集和Map集

    一.Set集合 1.概述 Set集合无序的.不可重复的元素(无序是指索引) Set集合不按照特定的方法进行排序,只是将元素放在集合中. 下面介绍一下Set集合的HashSet和TreeSet两个实现类 ...

  2. python-飞机大战

    效果图 main.py import time import pygame from EnemyPlane import EnemyPlane from HeroPlane import HeroPl ...

  3. Team Queue POJ - 2259 (队列)

    Queues and Priority Queues are data structures which are known to most computer scientists. The Team ...

  4. P3150 pb的游戏(1)

    P3150 pb的游戏(1)选偶数,这一轮一定会活,选奇数,自己这一轮可能会死,并且(如果自己这一轮没死)下一轮对手一定可以活,因为选了奇数,就会被分解成奇数和偶数. #include<iost ...

  5. jarvis OJ WEB题目writeup

    0x00前言 发现一个很好的ctf平台,题目感觉很有趣,学习了一波并记录一下 https://www.jarvisoj.com 0x01 Port51 题目要求是用51端口去访问该网页,注意下,要用具 ...

  6. 学习DRF之前

    在学习DRF之前~我们要先复习一些知识点~~ FBV和CBV的区别 学习Django的时候~我们已经了解过CBV以及FBV 什么是FBV和CBV呢~~ FBV 基于函数的视图 CBV 基于类的视图 也 ...

  7. 关于java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to 实体类

    由于业务逻辑的复杂,有些sql语句写法hql不支持,所以hibernate查询直接用了sql原生查询,由于数据结果根据四个表查询出来,所以无法使用方法.addEntity(XXXXXXX.class) ...

  8. 杭店 ACM 1864 最大报销额 01背包

    ![勾选C++才能过 题意: 先规定可以报销一定额度的发票,物品类型有A,B,C,三种.要求每张发票总额不得超过1000元,单项物品不得超过600.求报销的最大额 分析: 先找到合格的发票,然后再挑选 ...

  9. Map、Set使用过程中可能出现的问题

    修改了key之后不能remove class Student implements Serializable { Integer id; String name; public Student(Int ...

  10. 学习Struts--Chap07:Struts2文件上传和下载

    1.struts2文件上传 1.1.struts2文件上传的基本概述 在开发web应用的时候,我们一般会为用户提供文件上传的功能,比如用户上传一张图像作为头像等.为了能上传文件,我们必须将表单的met ...