9

关于.NET中的控制反转(三)- 依赖注入之最强 Autofac

 3 years ago
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版本的安装会失败。

RNzEF3b.png!mobile

三、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 }

AVFbEjE.png!mobile

五、引用地址

1:Autofac官网地址: https://autofaccn.readthedocs.io/zh/latest/

2:Autofac 测试用例代码: https://github.com/autofac/Autofac


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK