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/

 

你可能感兴趣的:(AutoFac记录)