阅读目录


一、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. Visual Studio 2019及其注册码

    Visual Studio 2019 更快地进行代码编写.更智能地执行操作.使用同类最佳IDE 创建未来.     下载Visual Studio         使用从初始设计到最终部署的完整工具集 ...

  2. Linux学习之后台任务与定时任务(二十)

    Linux学习之后台任务与定时任务 目录 后台任务 把进程放入后台 查看后台任务 将后台暂停的工作恢复到前台执行 将后台暂停的工作恢复到后台执行 定时任务 手动启动服务 将服务设置为自启动 用户的co ...

  3. Django基础(三)

    知识预览 Ajax前戏:json Ajax简介 jquery实现的ajax JS实现的ajax 回到顶部 Ajax前戏:json 什么是json? 定义: JSON(JavaScript Object ...

  4. go知识点和注意事项

    bin目录下面存的是编译之后可执行的文件,pkg下面存放的是应用包,src下面保存的是应用源代码 Go 语言不支持函数重载特性的主要原因是函数重载需要进行多余的类型匹配影响性能: 目前 Go 没有泛型 ...

  5. php 将两个数组进行相加 http://blog.csdn.net/lcstrive/article/details/38331487

    刚刚在网上看到一个提问. 数组Array ( [0] => 1 [1] => 2 )和数组Array ( [0] => 5 [1] => 6 ) 怎么让他们想加得出: 数组Ar ...

  6. Java 多线程 创建线程的4种方式

    1 继承Thread类,重写run方法.Thread类实现了Runnable接口. 2 实现Runnable接口,重写run方法.相比于继承Thread类,可以避免单继承的缺陷和实现资源共享. 举例: ...

  7. CSS 埋点统计

    原文地址: https://my.oschina.net/u/1778933/blog/1608904 CSS 埋点统计 当一个网站或者 App 的规模达到一定程度,需要分析用户在 App 或者网站的 ...

  8. netty源码解析目录

    第一章 java nio三大组件与使用姿势 二.netty使用姿势 三.netty服务端启动源码 四.netty客户端启动源码 五.NioEventLoop与netty线程模型 六.ChannelPi ...

  9. centos找不到环境变量 -bash: ls: command not found

    #在系统中输入命令,报如下错误: [root@a1 work]# ll-bash: ls: command not found #昨时解决办法:export PATH=/usr/local/sbin: ...

  10. Python学习笔记:Flask-Migrate基于model做upgrade的基本原理

      1)flask-migrate的官网:https://flask-migrate.readthedocs.io/en/latest/  2)获取帮助,在pycharm的控制台中输入 flask d ...