• AutoFac记录


    概念

    Autofac是一个轻量级的依赖注入的框架,同类型的框架还有Spring.NET,Unity,Castle等;

    ContainerBuilder:将组件注册成服务的创建者。

    组件:Lambda表达式/一个类型/一个预编译的实例/实例类型所在的程序集

    container 容器:通过 ContainerBuilder.Build()创建

    获得对象:container.Resolve();

    As()方法:可以指定相同的组件暴露成不同的服务。有些没有as就是将本身暴露给用户

     

     组件注册成服务(暴露给用户)

    常用注册的方式

    1.通过RegisterType

    2.同lambda表达式

    3.通过实例来注册

    4.程序集创建 RegisterAssemblyTypes

     5.泛型注册 RegisterGeneric 

      1  public class 注册方式
      2     {
      3         /// <summary>
      4         /// 1.RegisterType AutoFac能够通过反射检查一个类型,选择一个合适的构造函数,创造这个对象的实例
      5         /// </summary>
      6         [TestMethod]
      7         public void RegisterType()
      8         {
      9             var builder = new ContainerBuilder();
     10             builder.RegisterType<TestClass>();//方式1
     11             builder.RegisterType(typeof(TestClass));//方式2
     12             IContainer container = builder.Build();
     13             var class1 = container.Resolve<TestClass>();
     14             Assert.IsTrue(class1 != null);
     15         }
     16 
     17         /// <summary>
     18         /// 1.RegisterType Named 命名方式注册
     19         /// </summary>
     20         [TestMethod]
     21         public void RegisterType2()
     22         {
     23             var builder = new ContainerBuilder();
     24             builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
     25             IContainer container = builder.Build();
     26           //  var class1 = container.Resolve<TestClass>(); error
     27             var class2 = container.ResolveNamed<TestClass>("TestClass");
     28           //  Assert.IsTrue(class1 == null);
     29             Assert.IsTrue(class2 != null);
     30         }
     31 
     32 
     33         /// <summary>
     34         /// 2.Lambda  通过反射的方式实现
     35         /// </summary>
     36         [TestMethod]
     37         public void Lambda()
     38         {
     39             var builder = new ContainerBuilder();
     40             builder.Register(p=>new TestClass());
     41             IContainer container = builder.Build();
     42             var class1 = container.Resolve<TestClass>();
     43             Assert.IsTrue(class1 != null);
     44         }
     45 
     46 
     47         /// <summary>
     48         /// 3.RegisterInstance 实例创建
     49         /// </summary>
     50         [TestMethod]
     51         public void RegisterInstance1()
     52         {
     53             var builder = new ContainerBuilder();
     54             builder.RegisterInstance<TestClass>(new TestClass());
     55             IContainer container = builder.Build();
     56             var class1 = container.Resolve<TestClass>();
     57             Assert.IsTrue(class1 != null);
     58         }
     59 
     60         /// <summary>
     61         /// 3.RegisterInstance 将自己系统中原有的单例注册为容器托管的单例
     62         /// </summary>
     63         [TestMethod]
     64         public void RegisterInstance2()
     65         {
     66             var builder = new ContainerBuilder();
     67             builder.RegisterInstance(TestClass2.GetInstance()).ExternallyOwned();
     68             IContainer container = builder.Build();
     69             var class1 = container.Resolve<TestClass2>();
     70             Assert.IsTrue(class1 != null);
     71         }
     72 
     73 
     74         /// <summary>
     75         /// 4.RegisterAssemblyTypes 程序集的创建
     76         /// </summary>
     77         [TestMethod]
     78         public void RegisterAssemblyTypes()
     79         {
     80             var builder = new ContainerBuilder();
     81             builder.RegisterAssemblyTypes(Assembly.Load("UnitTestProject1")).Where(p => p.Name == "TestClass");
     82             IContainer container = builder.Build();
     83             var class1 = container.Resolve<TestClass>();
     84             Assert.IsTrue(class1 != null);
     85         }
     86 
     87 
     88 
     89         /// <summary>
     90         /// 5.RegisterGeneric 泛型注册
     91         /// </summary>
     92         [TestMethod]
     93         public void RegisterGeneric()
     94         {
     95             var builder = new ContainerBuilder();
     96             builder.RegisterGeneric(typeof(TestClass3<>));
     97             IContainer container = builder.Build();
     98             var myIntList = container.Resolve<TestClass3<int>>();
     99             Assert.IsTrue(myIntList != null);
    100             var myStringList = container.Resolve<TestClass3<string>>();
    101             Assert.IsTrue(myStringList != null);
    102         }
    103 
    104     }
    View Code

    注册方式扩展

    1.指定构造函数

    2.构造函数的参数

    3.属性注入

    4.方法注入

      1    public class 注册方式扩展
      2     {
      3         /// <summary>
      4         /// 构造函数注入
      5         /// Autofac默认从容器中选择参数最多的构造函数。如果想要选择一个不同的构造函数,就需要在注册的时候就指定它。
      6         /// *可以跟Name或者索引结合起来注册不同的构造函数
      7         /// </summary>
      8         [TestMethod]
      9         public void RegisterType()
     10         {
     11             var builder = new ContainerBuilder();
     12             builder.RegisterType<TestClass4Paramter1>();
     13             builder.RegisterType<TestClass4Paramter2>();
     14             builder.RegisterType<TestClass4>().UsingConstructor(typeof(TestClass4Paramter1));
     15             // builder.RegisterType<TestClass4>();
     16             IContainer container = builder.Build();
     17             var class1 = container.Resolve<TestClass4>();
     18             Assert.IsTrue(class1.dd == 1);
     19         }
     20 
     21 
     22 
     23         /// <summary>
     24         /// 构造函数参数 WithParameters WithParameter
     25         /// </summary>
     26         [TestMethod]
     27         public void RegisterType2()
     28         {
     29             var builder = new ContainerBuilder();
     30             //错误情况 多个参数
     31             //List<NamedParameter> ListNamedParameter = new List<NamedParameter>() 
     32             //{    new NamedParameter("paramter1", "dddd")  
     33             //};
     34             //builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter);
     35 
     36             //错误
     37            // builder.RegisterType<TestClass5>().WithParameter(new NamedParameter("paramter1", "dddd"));
     38 
     39             //错误
     40             // List<ResolvedParameter> ListNamedParameter = new List<ResolvedParameter>() 
     41             // {   new ResolvedParameter(
     42             //(pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "paramter1",
     43             //(pi, ctx) => "sectionName")
     44 
     45             // };
     46             // builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter);
     47 
     48 
     49             //正确情况
     50             //builder.RegisterType<TestClass5>().WithParameter("paramter1", "sectionName");
     51 
     52             IContainer container = builder.Build();
     53             var class1 = container.Resolve<TestClass5>();
     54             Assert.IsTrue(class1.dd == 1);
     55         }
     56 
     57         /// <summary>
     58         ///属性注入
     59         /// </summary>
     60         [TestMethod]
     61         public void RegisterType3()
     62         {
     63             var builder = new ContainerBuilder();
     64             builder.RegisterType<TestClass6>().WithProperty("dd", 1);
     65             IContainer container = builder.Build();
     66             var class1 = container.Resolve<TestClass6>();
     67             Assert.IsTrue(class1.dd == 1);
     68         }
     69 
     70         /// <summary>
     71         ///方法注入  指定注入的方法
     72         /// </summary>
     73         [TestMethod]
     74         public void RegisterType4()
     75         {
     76             var builder = new ContainerBuilder();
     77             builder.Register(c =>
     78             {
     79                 var result = new TestClass7();
     80                 result.SetDependency(c.Resolve<ITestClass7>());
     81                 return result;
     82             });
     83             IContainer container = builder.Build();
     84             var class1 = container.Resolve<TestClass7>();
     85             Assert.IsTrue(class1 != null);
     86         }
     87 
     88 
     89         /// <summary>
     90         ///方法注入   使用Activating Handler  指定自身注册完成后触发的事件
     91         /// </summary>
     92         [TestMethod]
     93         public void RegisterType5()
     94         {
     95             var builder = new ContainerBuilder();
     96             builder.Register<TestClass8>(c => new TestClass8()).OnActivating(e => e.Instance.SetDependency(new TestClass6()));
     97             IContainer container = builder.Build();
     98             var class1 = container.Resolve<TestClass8>();
     99             Assert.IsTrue(class1 != null);
    100         }
    101 
    102     }
    103 
    104 
    105     public class TestClass4
    106     {
    107         public int dd = 0;
    108 
    109         public TestClass4(TestClass4Paramter1 a)
    110         {
    111             dd = 1;
    112         }
    113 
    114         public TestClass4(TestClass4Paramter2 a)
    115         {
    116             dd = 2;
    117         }
    118 
    119         public TestClass4(TestClass4Paramter1 a, TestClass4Paramter2 b)
    120         {
    121             dd = 12;
    122         }
    123 
    124     }
    125 
    126     public class TestClass4Paramter1
    127     {
    128 
    129     }
    130 
    131     public class TestClass4Paramter2
    132     {
    133 
    134     }
    135 
    136 
    137     public class TestClass5
    138     {
    139         public int dd = 0;
    140         public TestClass5(string a)
    141         {
    142             dd = 1;
    143         }
    144 
    145     }
    146 
    147 
    148     public class TestClass6
    149     {
    150 
    151         public int dd { get; set; }
    152     }
    153 
    154 
    155     public class TestClass7
    156     {
    157         private ITestClass7 ITestClass7;
    158         public void SetDependency(ITestClass7 ITestClass7)
    159         {
    160             this.ITestClass7 = ITestClass7;
    161         }
    162     }
    163 
    164     public interface ITestClass7
    165     {
    166 
    167     }
    168 
    169 
    170     public class TestClass8
    171     {
    172 
    173         public void SetDependency(TestClass6 ITestClass6)
    174         {
    175             var t = ITestClass6.dd;
    176         }
    177     }
    View Code

     获取服务

    常用的获取服务的方式

     1  public class 获取服务
     2     {
     3         /// <summary>
     4         /// Resolve
     5         /// </summary>
     6         [TestMethod]
     7        public void Resolve()
     8        {
     9            var builder = new ContainerBuilder();
    10            builder.RegisterType<TestClass>();
    11            IContainer container = builder.Build();
    12            var class1 = container.Resolve<TestClass>();
    13            Assert.IsTrue(class1 != null);
    14        }
    15 
    16        /// <summary>
    17         /// ResolveNamed
    18        /// </summary>
    19         [TestMethod]
    20         public void ResolveNamed()
    21         {
    22             var builder = new ContainerBuilder();
    23             builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
    24             IContainer container = builder.Build();
    25             var class2 = container.ResolveNamed<TestClass>("TestClass");
    26             Assert.IsTrue(class2 != null);
    27         }
    28 
    29        /// <summary>
    30         /// ResolveKeyed 有Name的方式很方便,但是只支持字符串,但有时候我们可能需要通过其他类型作键。
    31        /// </summary>
    32         [TestMethod]
    33         public void ResolveKeyed()
    34         {
    35             var builder = new ContainerBuilder();
    36             builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
    37             IContainer container = builder.Build();
    38             var class2 = container.ResolveKeyed<TestClass>(TestState.服务1);
    39             Assert.IsTrue(class2 != null);
    40         }
    41 
    42         [TestMethod]
    43         public void ResolveIIndex()
    44         {
    45             var builder = new ContainerBuilder();
    46             builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
    47             IContainer container = builder.Build();
    48             IIndex<TestState, TestClass> IIndex = container.Resolve<IIndex<TestState, TestClass>>();
    49             TestClass p = IIndex[TestState.服务1];
    50             Assert.IsTrue(p != null);
    51         }
    52     }
    View Code

     获取服务扩展

    当注册或者检索component的时候可以使用参数。

      1、传递参数给Resolve

      Resolve接受可变参数或IEnumerable<T>传入多个值

        using (IContainer container = builder.Build())
        {
            AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
            Console.WriteLine(manager.Name);    //输出 刘备
            manager.Say();
        }

      此时,AutoFacManager下必须添加如下构造函数

        public AutoFacManager(string name,IPerson MyPerson)
        {
            Name = name;
            person = MyPerson;
        }

      2、可用的参数类型

      Autofac提供几种不同的参数对应策略:

    1. NamedParameter :像上面那样对应的参数名字
    2. TypedParameter:对应到参数的类型(必须是具体的类型)
    3. ResolvedParameter:灵活的参数匹配
    4. NamedParameter 和TypedParameter:只能提供常量参数

      3、从表达式中使用参数

      如果使用表达式注册的方式,可以使用第二个可用的委托参数来获得参数。

    复制代码
        builder.Register((c, p) => new AutoFacManager(p.Named<string>("name"), c.Resolve<IPerson>()));
        builder.RegisterType<Worker>().As<IPerson>();
        using (IContainer container = builder.Build())
        {
            AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
            Console.WriteLine(manager.Name);    //输出刘备
            manager.Say();
        }

    特殊问题

    循环依赖

    生命周期

    生命周期不同阶段使用的事件

    主要用于处理一些依赖关系比如在初始化该类之前某个类必须初始化好

    或者当前类初始化后其他相关的类必须进行初始化 目前比较不常用

    Autofac暴露五个事件接口供实例的按如下顺序调用

    1. OnRegistered
    2. OnPreparing
    3. OnActivated
    4. OnActivating
    5. OnRelease
    builder.RegisterType<Worker>().As<IPerson>()
            .OnRegistered(e => Console.WriteLine("在注册的时候调用!"))
            .OnPreparing(e => Console.WriteLine("在准备创建的时候调用!"))
            .OnActivating(e => Console.WriteLine("在创建之前调用!"))
            .OnActivated(e => Console.WriteLine("创建之后调用!"))
            .OnRelease(e => Console.WriteLine("在释放占用的资源之前调用!"));

    默认有三种生命周期:

    1.Per Dependency:默认的生命周期 每次请求都创建一个新的对象
    2.Single Instance:单例模式  每次都用同一个对象
    3.Per Lifetime Scope:同一个生命周期生成的对象是同一个实例

     1  public class 生命周期
     2     {
     3         /// <summary>
     4         /// 默认生命周期
     5         /// </summary>
     6         [TestMethod]
     7         public void PerDependency()
     8         {
     9             var builder = new ContainerBuilder();
    10             builder.RegisterType<TestClass>().InstancePerDependency();
    11             IContainer container = builder.Build();
    12             var class1 = container.Resolve<TestClass>();
    13             var class2 = container.Resolve<TestClass>();
    14             Assert.IsFalse(object.ReferenceEquals(class1, class2));
    15         }
    16 
    17         /// <summary>
    18         /// 单例 每次都用同一个对象(不同用户使用相同的第一次实例)
    19         /// </summary>
    20         [TestMethod]
    21         public void SingleInstance()
    22         {
    23             var builder = new ContainerBuilder();
    24             builder.RegisterType<TestClass>().SingleInstance();
    25 
    26             IContainer container = builder.Build();
    27             var class1 = container.Resolve<TestClass>();
    28             var class2 = container.Resolve<TestClass>();
    29             Assert.IsTrue(object.ReferenceEquals(class1, class2));
    30         }
    31 
    32 
    33         /// <summary>
    34         /// 同一生命周期内使用同一个对象
    35         /// </summary>
    36         [TestMethod]
    37         public void PerLifetimeScope()
    38         {
    39             var builder = new ContainerBuilder();
    40             builder.RegisterType<TestClass>().InstancePerLifetimeScope();
    41 
    42             IContainer container = builder.Build();
    43             var class1 = container.Resolve<TestClass>();
    44             var class2 = container.Resolve<TestClass>();
    45 
    46             ILifetimeScope inner = container.BeginLifetimeScope();
    47             var class3 = inner.Resolve<TestClass>();
    48             var class4 = inner.Resolve<TestClass>();
    49 
    50             Assert.IsTrue(object.ReferenceEquals(class1, class2));
    51             Assert.IsFalse(object.ReferenceEquals(class1, class3));
    52             Assert.IsTrue(object.ReferenceEquals(class3, class4));
    53         }
    54 
    55 
    56     }
    View Code

    config配置注入

      static void Main(string[] args)
        {
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<AutoFacManager>();
            builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
            using (IContainer container = builder.Build())
            {
                AutoFacManager manager = container.Resolve<AutoFacManager>();
                manager.Say();
            } 
                
            Console.ReadKey();
        }



    AutoFac在MVC中的应用




    参考资料:http://docs.autofac.org/en/latest/

  • 相关阅读:
    Java-Class-C:com.alibaba.fastjosn.JSON.java
    兆芯笔试题(2015)找反复数最多的字母的数量以及位置
    获得文件属性的函数调用实例
    错了:用流量能够放肆,有wifi则要节制
    为什么会找不到D层文件?
    Cocos2d-x3.0游戏实例之《别救我》第六篇——从代码中获取UI控件
    Add Binary
    【iOS开发之Objective-C】书签管理器项目
    UVa 11732 strcmp() Anyone?
    【打CF,学算法——二星级】Codeforces Round #313 (Div. 2) B. Gerald is into Art(水题)
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/4905864.html
Copyright © 2020-2023  润新知