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


    一、Autofac简介

    Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成。Autofac的主要特性如下:

    • 组件侵入性为零:组件不需要去引用Autofac。
    • 灵活的模块化系统:通过模块化组织你的程序,应用程序不用纠缠于复 杂的XML配置系统或者是配置参数。
    • 自动装配:可以是用lambda表达式注册你的组件,autofac会根据需要选择构造函数或者属 性注入
    • XML配置文件的支持:XML配置文件过度使用时很丑陋,但是在发布的时候通常非常有用
    • 组件的多服务支持:许 多设计师喜欢使用细粒度的接口来控制依赖 , autofac允许一个组件提供多个服务

    二、Autofac安装

    1:使用Nuget下载 “Autofac”库,需注意,使用 .net framework必须在4.7以上版本,低于4.7版本的安装会失败。

    img

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

    img

    五、引用地址

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

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

    3:相关博文:关于.NET中的控制反转(二)- 依赖注入之 MEF关于.NET中的控制反转(一)- 概念与定义

  • 相关阅读:
    【openwrt】——lua字符串操作
    Andriod绘图的基础知识
    protect,public,private 的区别
    fatjar 将项目使用的第三方jar包打包(亲测可用)
    TPshop学习(8)微信支付
    HTTP和HTTPS有什么区别? 什么是SSL证书?使用ssl证书优势?
    LNMP安装Let’s Encrypt 免费SSL证书方法:自动安装与手动配置Nginx
    腾讯云中ssL证书的配置安装
    微信小程序:微信登陆(ThinkPHP作后台)
    转载VC6LineNumberAddin 规格严格
  • 原文地址:https://www.cnblogs.com/dongweian/p/14267998.html
Copyright © 2020-2023  润新知