一、為什麼使用Autofac? Autofac是.NET領域最為流行的IoC框架之一,傳說是速度最快的一個。 1.1、性能 有人專門做了測試: 1.2、優點 1)與C#語言聯繫很緊密。C#里的很多編程方式都可以為Autofac使用,例如可以使用Lambda表達式註冊組件。 2)較低的學習曲線。學習它 ...
一、為什麼使用Autofac?
Autofac是.NET領域最為流行的IoC框架之一,傳說是速度最快的一個。
1.1、性能
有人專門做了測試:
1.2、優點
1)與C#語言聯繫很緊密。C#里的很多編程方式都可以為Autofac使用,例如可以使用Lambda表達式註冊組件。
2)較低的學習曲線。學習它非常的簡單,只要你理解了IoC和DI的概念以及在何時需要使用它們。
3)支持JSON/XML配置。
4)自動裝配。
5)與Asp.Net MVC集成。
6)微軟的Orchad開源程式使用的就是Autofac,可以看出它的方便和強大。
1.3、資源
官方網站:http://autofac.org/
GitHub網址:https://github.com/autofac/Autofac
學習資料:Autofac中文文檔
二、數據準備
2.1、新建項目
IService下的介面類:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinkTo.Test.Autofac.IService { /// <summary> /// 動物吠聲介面類 /// </summary> public interface IAnimalBark { /// <summary> /// 吠叫 /// </summary> void Bark(); } }IAnimalBark
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinkTo.Test.Autofac.IService { /// <summary> /// 動物睡眠介面類 /// </summary> public interface IAnimalSleep { /// <summary> /// 睡眠 /// </summary> void Sleep(); } }IAnimalSleep
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinkTo.Test.Autofac.IService { /// <summary> /// 學校介面類 /// </summary> public interface ISchool { /// <summary> /// 放學 /// </summary> void LeaveSchool(); } }ISchool
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinkTo.Test.Autofac.IService { /// <summary> /// 學生介面類 /// </summary> public interface IStudent { /// <summary> /// 增加學生 /// </summary> /// <param name="studentID">學生ID</param> /// <param name="studentName">學生姓名</param> void Add(string studentID, string studentName); } }IStudent
Service下的介面實現類:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LinkTo.Test.Autofac.IService; namespace LinkTo.Test.Autofac.Service { /// <summary> /// 貓類 /// </summary> public class Cat : IAnimalSleep { /// <summary> /// 睡眠 /// </summary> public void Sleep() { Console.WriteLine("小貓咪睡著了zZ"); } } }Cat
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LinkTo.Test.Autofac.IService; namespace LinkTo.Test.Autofac.Service { /// <summary> /// 狗類 /// </summary> public class Dog : IAnimalBark, IAnimalSleep { /// <summary> /// 吠叫 /// </summary> public void Bark() { Console.WriteLine("汪汪汪"); } /// <summary> /// 睡眠 /// </summary> public void Sleep() { Console.WriteLine("小狗狗睡著了zZ"); } } }Dog
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LinkTo.Test.Autofac.IService; namespace LinkTo.Test.Autofac.Service { /// <summary> /// 學校類 /// </summary> public class School : ISchool { /// <summary> /// IAnimalBark屬性 /// </summary> public IAnimalBark AnimalBark { get; set; } /// <summary> /// 放學 /// </summary> public void LeaveSchool() { AnimalBark.Bark(); Console.WriteLine("你家的熊孩子放學了⊙o⊙"); } } }School
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LinkTo.Test.Autofac.IService; namespace LinkTo.Test.Autofac.Service { /// <summary> /// 學生類 /// </summary> public class Student : IStudent { /// <summary> /// 無參構造函數 /// </summary> public Student() { } /// <summary> /// 有參構造函數 /// </summary> /// <param name="studentID">學生ID</param> /// <param name="studentName">學生姓名</param> public Student(string studentID, string studentName) { Add(studentID, studentName); } /// <summary> /// 增加學生 /// </summary> /// <param name="studentID">學生ID</param> /// <param name="studentName">學生姓名</param> public void Add(string studentID, string studentName) { Console.WriteLine($"新增的學生是:{studentName}"); } } }Student
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using LinkTo.Test.Autofac.IService; namespace LinkTo.Test.Autofac.Service { /// <summary> /// 動物搖尾巴 /// </summary> public class AnimalWagging { /// <summary> /// IAnimalBark屬性 /// </summary> IAnimalBark animalBark; /// <summary> /// 有參構造函數 /// </summary> /// <param name="bark">IAnimalBark變數</param> public AnimalWagging(IAnimalBark bark) { animalBark = bark; } /// <summary> /// 搖尾巴 /// </summary> public virtual void Wagging() { animalBark.Bark(); Console.WriteLine("搖尾巴"); } /// <summary> /// 計數 /// </summary> /// <returns></returns> public static int Count() { return 6; } /// <summary> /// 任務 /// </summary> /// <param name="name">動物名稱</param> /// <returns></returns> public virtual async Task<string> WaggingAsync(string name) { var result = await Task.Run(() => Count()); return $"{name}搖了{result}下尾巴"; } } }AnimalWagging
2.2、Autofac安裝
Client項目右鍵->管理 NuGet 程式包->Autofac。
三、IoC-註冊
3.1、類型註冊
a)類型註冊:使用RegisterType進行註冊。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//註冊Autofac組件 ContainerBuilder builder = new ContainerBuilder(); //註冊實現類Student,當我們請求IStudent介面的時候,返回的是類Student的對象。 builder.RegisterType<Student>().As<IStudent>(); //上面這句也可改成下麵這句,這樣請求Student實現了的任何介面的時候,都會返回Student對象。 //builder.RegisterType<Student>().AsImplementedInterfaces(); IContainer container = builder.Build(); //請求IStudent介面 IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello");View Code
b)類型註冊(別名):假如一個介面有多個實現類,可以在註冊時起別名。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Dog>().Named<IAnimalSleep>("Dog"); builder.RegisterType<Cat>().Named<IAnimalSleep>("Cat"); IContainer container = builder.Build(); var dog = container.ResolveNamed<IAnimalSleep>("Dog"); dog.Sleep(); var cat = container.ResolveNamed<IAnimalSleep>("Cat"); cat.Sleep();View Code
c)類型註冊(枚舉):假如一個介面有多個實現類,也可以使用枚舉的方式註冊。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public enum AnimalType { Dog, Cat }View Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Dog>().Keyed<IAnimalSleep>(AnimalType.Dog); builder.RegisterType<Cat>().Keyed<IAnimalSleep>(AnimalType.Cat); IContainer container = builder.Build(); var dog = container.ResolveKeyed<IAnimalSleep>(AnimalType.Dog); dog.Sleep(); var cat = container.ResolveKeyed<IAnimalSleep>(AnimalType.Cat); cat.Sleep();View Code
3.2、實例註冊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterInstance<IStudent>(new Student()); IContainer container = builder.Build(); IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello");View Code
3.3、Lambda註冊
a)Lambda註冊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.Register(c => new Student()).As<IStudent>(); IContainer container = builder.Build(); IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello");View Code
b)Lambda註冊(NamedParameter)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.Register<IAnimalSleep>((c, p) => { var type = p.Named<string>("type"); if (type == "Dog") { return new Dog(); } else { return new Cat(); } }).As<IAnimalSleep>(); IContainer container = builder.Build(); var dog = container.Resolve<IAnimalSleep>(new NamedParameter("type", "Dog")); dog.Sleep();View Code
3.4、程式集註冊
如果有很多介面及實現類,假如覺得這種一一註冊很麻煩的話,可以一次性全部註冊,當然也可以加篩選條件。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //實現類所在的程式集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces(); //常用 //builder.RegisterAssemblyTypes(assembly).Where(t=>t.Name.StartsWith("S")).AsImplementedInterfaces(); //帶篩選 //builder.RegisterAssemblyTypes(assembly).Except<School>().AsImplementedInterfaces(); //帶篩選 IContainer container = builder.Build(); //單實現類的用法 IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello"); //多實現類的用法 IEnumerable<IAnimalSleep> animals = container.Resolve<IEnumerable<IAnimalSleep>>(); foreach (var item in animals) { item.Sleep(); }View Code
3.5、泛型註冊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterGeneric(typeof(List<>)).As(typeof(IList<>)); IContainer container = builder.Build(); IList<string> list = container.Resolve<IList<string>>();View Code
3.6、預設註冊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); //對於同一個介面,後面註冊的實現會覆蓋之前的實現。 //如果不想覆蓋的話,可以用PreserveExistingDefaults,這樣會保留原來註冊的實現。 builder.RegisterType<Dog>().As<IAnimalSleep>(); builder.RegisterType<Cat>().As<IAnimalSleep>().PreserveExistingDefaults(); //指定為非預設值 IContainer container = builder.Build(); var dog = container.Resolve<IAnimalSleep>(); dog.Sleep();View Code
四、IoC-註入
4.1、構造函數註入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<AnimalWagging>(); builder.RegisterType<Dog>().As<IAnimalBark>(); IContainer container = builder.Build(); AnimalWagging animal = container.Resolve<AnimalWagging>(); animal.Wagging();View Code
4.2、屬性註入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //實現類所在的程式集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired(); //常用 IContainer container = builder.Build(); ISchool school = container.Resolve<ISchool>(); school.LeaveSchool();View Code
五、IoC-事件
Autofac在組件生命周期的不同階段,共對應了5個事件,執行順序如下所示:
1.OnRegistered->2.OnPreparing->3.OnActivating->4.OnActivated->5.OnRelease
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<Student>().As<IStudent>() .OnRegistered(e => Console.WriteLine("OnRegistered:在註冊的時候調用")) .OnPreparing(e => Console.WriteLine("OnPreparing:在準備創建的時候調用")) .OnActivating(e => Console.WriteLine("OnActivating:在創建之前調用")) //.OnActivating(e => e.ReplaceInstance(new Student("1000", "Test"))) .OnActivated(e => Console.WriteLine("OnActivated:在創建之後調用")) .OnRelease(e => Console.WriteLine("OnRelease:在釋放占用的資源之前調用")); using (IContainer container = builder.Build()) { IStudent student = container.Resolve<IStudent>(); student.Add("1001", "Hello"); }View Code
六、IoC-生命周期
6.1、Per Dependency
Per Dependency:為預設的生命周期,也被稱為"transient"或"factory",其實就是每次請求都創建一個新的對象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //實現類所在的程式集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().InstancePerDependency(); //常用 IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(school1.Equals(school2));View Code
6.2、Single Instance
Single Instance:就是每次都用同一個對象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); Assembly assembly = Assembly.Load("LinkTo.Test.Autofac.Service"); //實現類所在的程式集名稱 builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().PropertiesAutowired().SingleInstance(); //常用 IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(ReferenceEquals(school1, school2));View Code
6.3、Per Lifetime Scope
Per Lifetime Scope:同一個Lifetime生成的對象是同一個實例。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ContainerBuilder builder = new ContainerBuilder(); builder.RegisterType<School>().As<ISchool>().InstancePerLifetimeScope(); IContainer container = builder.Build(); ISchool school1 = container.Resolve<ISchool>(); ISchool school2 = container.Resolve<ISchool>(); Console.WriteLine(school1.Equals(school2)); using (ILifetimeScope lifetime = container.BeginLifetimeScope()) { ISchool school3 = lifetime.Resolve<ISchool>(); ISchool school4 = lifetime.Resolve<ISchool>(); Console.WriteLine(school3.Equals(school4)); Console.WriteLine(school2.Equals(school3)); }View Code
七、IoC-通過配置文件使用Autofac
7.1、組件安裝
Client項目右鍵->管理 NuGet 程式包->Autofac.Configuration及Microsoft.Extensions.Configuration.Xml。
7.2、配置文件
新建一個AutofacConfigIoC.xml文件,在其屬性的複製到輸出目錄項下選擇始終複製。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8" ?> <autofac defaultAssembly="LinkTo.Test.Autofac.IService"> <!--無註入--> <components name="1001"> <type>LinkTo.Test.Autofac.Service.Student, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.IService.IStudent" /> <injectProperties>true</injectProperties> </components> <components name="1002"> <type>LinkTo.Test.Autofac.Service.Dog, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.IService.IAnimalBark" /> <injectProperties>true</injectProperties> </components> <!--構造函數註入--> <components name="2001"> <type>LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service</type> <services name="0" type="LinkTo.Test.Autofac.Service.AnimalWagging, LinkTo.Test.Autofac.Service" /> <injectProperties>true</injectProperties> </components> <!--屬性註入--> <components name="3001">