

关于.NET中的控制反转(三)- 依赖注入之最强 Autofac
source link: http://www.cnblogs.com/dongweian/p/14267998.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、Autofac简介
Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成。Autofac的主要特性如下:
- 组件侵入性为零:组件不需要去引用Autofac。
- 灵活的模块化系统:通过模块化组织你的程序,应用程序不用纠缠于复 杂的XML配置系统或者是配置参数。
- 自动装配:可以是用lambda表达式注册你的组件,autofac会根据需要选择构造函数或者属 性注入
- XML配置文件的支持:XML配置文件过度使用时很丑陋,但是在发布的时候通常非常有用
- 组件的多服务支持:许 多设计师喜欢使用细粒度的接口来控制依赖 , autofac允许一个组件提供多个服务
二、Autofac安装
1:使用Nuget下载 “Autofac”库,需注意,使用 .net framework必须在4.7以上版本,低于4.7版本的安装会失败。
三、Autofac的注册 —— 使用类型进行注册与使用
1 using Autofac; 2 using System; 3 4 namespace BankOperation 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 // 创建 ContainerBuilder 11 ContainerBuilder builder = new ContainerBuilder(); 12 13 // 注册 14 builder.RegisterType<ABank>().As<IUnionPay>(); 15 16 // 实例化 17 IContainer container = builder.Build(); 18 var dev = container.Resolve<IUnionPay>(); 19 dev.SaveMoneny(80); 20 dev.WithdrawMoney(50); 21 22 Console.ReadKey(); 23 } 24 25 } 26 27 public interface IUnionPay 28 { 29 /// <summary> 30 /// 存钱 31 /// </summary> 32 /// <param name="amount">存钱金额</param> 33 void SaveMoneny(int amount); 34 35 /// <summary> 36 /// 取钱 37 /// </summary> 38 /// <param name="amount">取钱金额</param> 39 void WithdrawMoney(int amount); 40 } 41 42 public class ABank:IUnionPay 43 { 44 public void SaveMoneny(int amount) 45 { 46 Console.WriteLine($"把钱存入A银行,金额为:{amount}"); 47 } 48 49 public void WithdrawMoney(int amount) 50 { 51 Console.WriteLine($"从A银行取钱,金额为:{amount}"); 52 } 53 } 54 }
四、Autofac的注册 —— 使用别名进行注册与使用(一个接口有多个实现类时)
1 using Autofac; 2 using System; 3 4 namespace BankOperation 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 Console.Write("请输入银行名称:"); 11 string name = Console.ReadLine(); 12 Operation(name); 13 14 Console.ReadKey(); 15 } 16 17 static void Operation(string name) 18 { 19 // 创建 ContainerBuilder 20 ContainerBuilder builder = new ContainerBuilder(); 21 22 // 使用别名进行注册 23 builder.RegisterType<ABank>().Named<IUnionPay>("A"); 24 builder.RegisterType<BBank>().Named<IUnionPay>("B"); 25 26 // 使用别名进行实例化 27 IContainer container = builder.Build(); 28 var dev = container.ResolveNamed<IUnionPay>(name); 29 dev.SaveMoneny(80); 30 dev.WithdrawMoney(50); 31 } 32 } 33 34 public interface IUnionPay 35 { 36 /// <summary> 37 /// 存钱 38 /// </summary> 39 /// <param name="amount">存钱金额</param> 40 void SaveMoneny(int amount); 41 42 /// <summary> 43 /// 取钱 44 /// </summary> 45 /// <param name="amount">取钱金额</param> 46 void WithdrawMoney(int amount); 47 } 48 49 public class ABank:IUnionPay 50 { 51 public void SaveMoneny(int amount) 52 { 53 Console.WriteLine($"把钱存入A银行,金额为:{amount}"); 54 } 55 56 public void WithdrawMoney(int amount) 57 { 58 Console.WriteLine($"从A银行取钱,金额为:{amount}"); 59 } 60 } 61 62 public class BBank : IUnionPay 63 { 64 public void SaveMoneny(int amount) 65 { 66 Console.WriteLine($"把钱存入B银行,金额为:{amount}"); 67 } 68 69 public void WithdrawMoney(int amount) 70 { 71 Console.WriteLine($"从B银行取钱,金额为:{amount}"); 72 } 73 } 74 }
五、Autofac的注册 —— 使用Lambda进行注册与使用(传递参数时)
反射在组件创建时是个很好的选择. 但是, 当组件创建不再是简单的调用构造方法时, 事情将变得混乱起来。可通过Lambda表达式传递一个实例,通过实例的初始化函数和公共属性传递需要注入的信息:
1 using Autofac; 2 using System; 3 4 namespace BankOperation 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 // 创建 ContainerBuilder 11 ContainerBuilder builder = new ContainerBuilder(); 12 13 // 注册(通过实例化函数传递参数+类的公共属性) 14 builder.Register<IUnionPay>(c => new ABank("测试A银行"){ BankRate =8.12}); 15 16 // 实例化 17 IContainer container = builder.Build(); 18 var dev = container.Resolve<IUnionPay>(); 19 dev.SaveMoneny(80); 20 dev.WithdrawMoney(50); 21 22 Console.ReadKey(); 23 } 24 25 } 26 27 public interface IUnionPay 28 { 29 /// <summary> 30 /// 存钱 31 /// </summary> 32 /// <param name="amount">存钱金额</param> 33 void SaveMoneny(int amount); 34 35 /// <summary> 36 /// 取钱 37 /// </summary> 38 /// <param name="amount">取钱金额</param> 39 void WithdrawMoney(int amount); 40 } 41 42 public class ABank:IUnionPay 43 { 44 /// <summary> 45 /// 银行利率 46 /// </summary> 47 public double BankRate { get; set; } 48 public ABank(string name) 49 { 50 Console.WriteLine($"银行名称:{name}"); 51 } 52 public void SaveMoneny(int amount) 53 { 54 Console.WriteLine($"把钱存入A银行(利率:{BankRate}%),金额为:{amount}"); 55 } 56 57 public void WithdrawMoney(int amount) 58 { 59 Console.WriteLine($"从A银行取钱,金额为:{amount}"); 60 } 61 } 62 }
当接口类有多个实现类,实现方式如下:
1 using Autofac; 2 using System; 3 4 namespace BankOperation 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 Console.Write("请输入银行名称:"); 11 string name = Console.ReadLine(); 12 Operation(name); 13 14 Console.ReadKey(); 15 } 16 17 static void Operation(string name) 18 { 19 // 创建 ContainerBuilder 20 ContainerBuilder builder = new ContainerBuilder(); 21 22 // 注册(通过实例化函数传递参数+类的公共属性) 23 builder.Register(c => new ABank("测试A银行") { BankRate = 8.12 }).Named<IUnionPay>("A"); 24 builder.Register(c => new ABank("测试B银行") { BankRate = 10.25 }).Named<IUnionPay>("B"); 25 26 // 实例化 27 IContainer container = builder.Build(); 28 var dev = container.ResolveNamed<IUnionPay>(name); 29 dev.SaveMoneny(80); 30 dev.WithdrawMoney(50); 31 } 32 33 } 34 35 public interface IUnionPay 36 { 37 /// <summary> 38 /// 存钱 39 /// </summary> 40 /// <param name="amount">存钱金额</param> 41 void SaveMoneny(int amount); 42 43 /// <summary> 44 /// 取钱 45 /// </summary> 46 /// <param name="amount">取钱金额</param> 47 void WithdrawMoney(int amount); 48 } 49 50 public class ABank:IUnionPay 51 { 52 /// <summary> 53 /// 银行利率 54 /// </summary> 55 public double BankRate { get; set; } 56 public ABank(string name) 57 { 58 Console.WriteLine($"银行名称:{name}"); 59 } 60 public void SaveMoneny(int amount) 61 { 62 Console.WriteLine($"把钱存入A银行(利率:{BankRate}%),金额为:{amount}"); 63 } 64 65 public void WithdrawMoney(int amount) 66 { 67 Console.WriteLine($"从A银行取钱,金额为:{amount}"); 68 } 69 } 70 71 public class BBank : IUnionPay 72 { 73 /// <summary> 74 /// 银行利率 75 /// </summary> 76 public double BankRate { get; set; } 77 public BBank(string name) 78 { 79 Console.WriteLine($"银行名称:{name}"); 80 } 81 public void SaveMoneny(int amount) 82 { 83 Console.WriteLine($"把钱存入B银行(利率:{BankRate}%),金额为:{amount}"); 84 } 85 86 public void WithdrawMoney(int amount) 87 { 88 Console.WriteLine($"从B银行取钱,金额为:{amount}"); 89 } 90 } 91 }
四、程序集注册
以上方法全部都要进行手动注册,如果有很多接口及实现类,这种一一注册的方式很麻烦,我们可以一次性全部注册,当然也可以加筛选条件。
1 using Autofac; 2 using System; 3 using System.Collections.Generic; 4 using System.Reflection; 5 6 namespace BankOperation 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Operation(); 13 14 Console.ReadKey(); 15 } 16 17 static void Operation() 18 { 19 // 创建 ContainerBuilder 20 ContainerBuilder builder = new ContainerBuilder(); 21 22 //实现类所在的程序集名称 23 Assembly assembly = Assembly.Load("BankOperation"); 24 25 // 获取程序集所在的全部实现类 26 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces(); 27 28 // t.Name.StartsWith:通过类名添加筛选条件,从类名的起始位开始匹配 29 builder.RegisterAssemblyTypes(assembly).Where(t => t.Name.StartsWith("B")).AsImplementedInterfaces(); 30 31 // 实例化 32 IContainer container = builder.Build(); 33 IEnumerable<IUnionPay> banks = container.Resolve<IEnumerable<IUnionPay>>(); 34 35 foreach (var item in banks) 36 { 37 item.SaveMoneny(100); 38 item.WithdrawMoney(20); 39 Console.WriteLine("-----------------------------------------------"); 40 } 41 } 42 43 } 44 45 public interface IUnionPay 46 { 47 /// <summary> 48 /// 存钱 49 /// </summary> 50 /// <param name="amount">存钱金额</param> 51 void SaveMoneny(int amount); 52 53 /// <summary> 54 /// 取钱 55 /// </summary> 56 /// <param name="amount">取钱金额</param> 57 void WithdrawMoney(int amount); 58 } 59 60 public class ABank:IUnionPay 61 { 62 public void SaveMoneny(int amount) 63 { 64 Console.WriteLine($"把钱存入A银行,金额为:{amount}"); 65 } 66 67 public void WithdrawMoney(int amount) 68 { 69 Console.WriteLine($"从A银行取钱,金额为:{amount}"); 70 } 71 } 72 73 public class BBank : IUnionPay 74 { 75 public void SaveMoneny(int amount) 76 { 77 Console.WriteLine($"把钱存入B银行,金额为:{amount}"); 78 } 79 80 public void WithdrawMoney(int amount) 81 { 82 Console.WriteLine($"从B银行取钱,金额为:{amount}"); 83 } 84 } 85 }
五、引用地址
1:Autofac官网地址: https://autofaccn.readthedocs.io/zh/latest/
2:Autofac 测试用例代码: https://github.com/autofac/Autofac
Recommend
-
84
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解。
-
13
IoC — Inversion of Control,控制反转 DI — Dependency Injection,依赖注入 IOC,是一种设计原则: 通过将组件(Components)的设置和使用分开,来降低类别或模组之间的耦合度(...
-
11
[ASP.NET Core 3框架揭秘] 依赖注入[1]:控制反转 ASP.NET Co...
-
8
控制反转和依赖注入的概念在网络上有大量的解释,很多都非常的详细,但对我来说过多的解释,容易把我绕来绕去,昨天听大佬的课,突然清晰地顿悟了。希望通过简单的描述,记录我的理解。 控制反转(IOC): 下面通过两张简单的图,了解一下控制反转的思...
-
9
ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了“标准化”,我们将这些标准化的组件称为服务,ASP.NET在内部专门维护了一个DI容器来提供所需...
-
8
记Quartz中使用AutoFac依赖注入遇到的问题发布于 8 月 15 日 最近在做一个需求,就是在Job中捕捉异常,然后通过邮件或者消息的方式推送给指定人员,在需求实现...
-
11
控制反转、依赖注入、服务定位 发表于 2021-06-07...
-
8
通过这篇文章,你将了解到 控制反转(IoC)是什么?「反转」到底反转了什么? Spring和IOC之间是什么关系? 依赖注入(DI)和依赖倒置原则(DIP)又是什么? IOC、DI和DIP有什么关系? 1....
-
6
IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 A 将取决于类 B,而 B 类又取决于类 C...
-
12
Spring中的IOC 一种思想,两种实现方式 IOC (Inversion of Control):控制反转,是一种概念和思想,指由Spring容器完成对象创建和依赖注入 核心业务:(a)对象的创建 (b)依赖的注入
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK