Autofac是一個.net下非常優秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP簡直是如虎添翼。Autofac的AOP是通過Castle(也是一個容器)項目的核心部分實現的,名為Autofac.Extras.DynamicProxy,顧名思義,其實現方式為動態代理。
使用方式比較簡單,先新建一個控制台項目,然后在Nuget上搜索Autofac.Aop並安裝,如下順序:
或者通過命令安裝:
Install-Package Autofac.Aop
安裝成功之后會項目會增加幾個個引用,如下圖:
1. 創建攔截器

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; //先在Nuget上搜索Autofac.Aop安裝 using Castle.DynamicProxy; namespace AutofacDEMO { /// <summary> /// 攔截器 需要實現 IInterceptor接口 Intercept方法 /// </summary> public class LogInterceptor : IInterceptor { /// <summary> /// 攔截方法 打印被攔截的方法執行前的名稱、參數和方法執行后的 返回結果 /// </summary> /// <param name="invocation">包含被攔截方法的信息</param> public void Intercept(IInvocation invocation) { Console.WriteLine("方法執行前:攔截{0}類下的方法{1}的參數是{2}", invocation.InvocationTarget.GetType(), invocation.Method.Name, string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())); //在被攔截的方法執行完畢后 繼續執行 invocation.Proceed(); Console.WriteLine("方法執行完畢,返回結果:{0}", invocation.ReturnValue); Console.WriteLine(); } } }
2. 創建攔截容器
var builder = new ContainerBuilder();
3. 注冊攔截器到Autofac容器
攔截器必須注冊到Aufofac容器中,可以通過攔截器類型或者命名注入,這兩種方式會讓使用攔截器的方法有所不同
// 命名注入 builder.Register(c => new LogInterceptor()).Named<IInterceptor>("log-calls"); //類型注入 builder.Register(c => new LogInterceptor());
//或者 builder.RegisterType<LogInterceptor>();
4. 啟用攔截器
啟用攔截器主要有兩個方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
EnableInterfaceInterceptors方法會動態創建一個接口代理
EnableClassInterceptors方法會創建一個目標類的子類代理類,這里需要注意的是只會攔截虛方法,重寫方法
注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面兩個方法
//啟用類代理攔截 //方式一:給類型上加特性Attribute builder.RegisterType<Student>().EnableClassInterceptors(); //方式二:在注冊類型到容器的時候動態注入攔截器(去掉類型上的特性Attribute) builder.RegisterType<Teacher>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //啟用接口代理攔截 //方式一:給類型上加特性Attribute builder.RegisterType<Man>().As<IPerson>().EnableInterfaceInterceptors(); //方式二:在注冊類型到容器的時候動態注入攔截器(去掉類型上的特性Attribute) builder.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors();
5. 指明要攔截的類型
有兩種方法:
第一種:給類型加上特性Attribute
第二種:在注冊類型到容器的時候動態注入攔截器
//動態注入攔截器 builder.RegisterType<Student>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors();
6. 測試效果如下
第一種:類代理攔截

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { /// <summary> /// 繼承接口,並實現方法,給類型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Student { public string Name; public Teacher Teacher; public Subject Subject; /// <summary> /// 必須是虛方法 /// </summary> public virtual void Say() { Console.WriteLine("你正在調用Say方法!學生姓名:" + Name); } } [Intercept(typeof(LogInterceptor))] public class Teacher { /// <summary> /// 必須是虛方法 /// </summary> public virtual void Show() { Console.WriteLine("I am Teacher's class !"); } } public class Subject { /// <summary> /// 必須是虛方法 /// </summary> public virtual void Show() { Console.WriteLine("I am Subject's class !" ); } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { class Program { static void Main(string[] args) { //啟用攔截器主要有兩個方法:EnableInterfaceInterceptors(),EnableClassInterceptors() //EnableInterfaceInterceptors方法會動態創建一個接口代理 //EnableClassInterceptors方法會創建一個目標類的子類代理類,這里需要注意的是只會攔截虛方法,重寫方法 //注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面兩個方法 #region 啟用類代理攔截 //創建攔截容器 var builder = new ContainerBuilder(); //注冊攔截器到容器 builder.RegisterType<LogInterceptor>(); //方式一:給類型上加特性Attribute builder.RegisterType<Student>().EnableClassInterceptors(); builder.RegisterType<Teacher>().EnableClassInterceptors(); //方式二:在注冊類型到容器的時候動態注入攔截器(去掉類型上的特性Attribute) //builder.RegisterType<Teacher>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //builder.RegisterType<Student>().InterceptedBy(typeof(LogInterceptor)).EnableClassInterceptors(); //屬性注入 builder.Register(c => new Student { Teacher = c.Resolve<Teacher>(), Subject = new Subject(), Name = "張三" }); using (var container = builder.Build()) { //從容器獲取對象 var Student = container.Resolve<Student>(); Student.Say(); Student.Subject.Show(); Student.Teacher.Show(); } Console.ReadLine(); #endregion } } }
第二種:接口代理攔截

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AutofacDEMO { /// <summary> /// 定義一個接口 /// </summary> public interface IPerson { void Say(string Name); } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { /// <summary> /// 繼承接口,並實現方法,給類型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Man: IPerson { public string Age; public void Say(string Name) { Console.WriteLine("男人調用Say方法!姓名:" + Name + ",年齡:" + Age); } } /// <summary> /// 繼承接口,並實現方法,給類型加上特性Attribute /// </summary> [Intercept(typeof(LogInterceptor))] public class Woman : IPerson { public void Say(string Name) { Console.WriteLine("女人調用Say方法!姓名:" + Name); } } /// <summary> /// 管理類 /// </summary> public class PersonManager { IPerson _Person; /// <summary> /// 根據傳入的類型動態創建對象 /// </summary> /// <param name="ds"></param> public PersonManager(IPerson Person) { _Person = Person; } public void Say(string Name) { _Person.Say(Name); } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autofac; using Autofac.Extras.DynamicProxy2; namespace AutofacDEMO { class Program { static void Main(string[] args) { //啟用攔截器主要有兩個方法:EnableInterfaceInterceptors(),EnableClassInterceptors() //EnableInterfaceInterceptors方法會動態創建一個接口代理 //EnableClassInterceptors方法會創建一個目標類的子類代理類,這里需要注意的是只會攔截虛方法,重寫方法 //注意:需要引用Autofac.Extras.DynamicProxy2才能使用上面兩個方法 #region 啟用接口代理攔截(推薦用這種方式) //創建攔截容器 var builder2 = new ContainerBuilder(); //注冊攔截器到容器 builder2.RegisterType<LogInterceptor>(); //構造函數注入(只要調用者傳入實現該接口的對象,就實現了對象創建,下面兩種方式) builder2.RegisterType<PersonManager>(); //方式一:給類型上加特性Attribute //屬性注入 builder2.Register<Man>(c => new Man { Age = "20" }).As<IPerson>().EnableInterfaceInterceptors(); //builder2.RegisterType<Man>().As<IPerson>().EnableInterfaceInterceptors(); builder2.RegisterType<Woman>().Named<IPerson>("Woman").EnableInterfaceInterceptors(); //方式二:在注冊類型到容器的時候動態注入攔截器(去掉類型上的特性Attribute) //builder2.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); //builder2.RegisterType<Woman>().Named<IPerson>("Woman").InterceptedBy(typeof(LogInterceptor)).EnableInterfaceInterceptors(); using (var container = builder2.Build()) { //從容器獲取對象 var Manager = container.Resolve<PersonManager>(); Manager.Say("管理員"); var Person = container.Resolve<IPerson>(); Person.Say("張三"); var Woman = container.ResolveNamed<IPerson>("Woman"); Woman.Say("王萌"); } Console.ReadLine(); #endregion } } }
Autofac三種生命周期:InstancePerLifetimeScope、SingleInstance、InstancePerDependency
InstancePerLifetimeScope:同一個Lifetime生成的對象是同一個實例
SingleInstance:單例模式,每次調用,都會使用同一個實例化的對象;每次都用同一個對象;
InstancePerDependency:默認模式,每次調用,都會重新實例化對象;每次請求都創建一個新的對象
//方式二:在注冊類型到容器的時候動態注入攔截器(去掉類型上的特性Attribute) builder.RegisterType<Man>().As<IPerson>().InterceptedBy(typeof(LogInterceptor)).InstancePerLifetimeScope().EnableInterfaceInterceptors();
看下面運行結果圖
1、InstancePerLifetimeScope
2、SingleInstance
3、InstancePerDependency
AsImplementedInterfaces() 是以接口方式進行注入,注入這些類的所有的公共接口作為服務(除了釋放資源)
builder.RegisterAssemblyTypes 注冊程序集中符合條件的類型
Assembly assembly = Assembly.Load(assemblyName); //Assembly assembly = this.GetType().GetTypeInfo().Assembly; builder.RegisterAssemblyTypes(assembly).Where(type => !type.IsInterface && !type.IsSealed && !type.IsAbstract && type.Name.EndsWith("BLL", StringComparison.OrdinalIgnoreCase)) .AsImplementedInterfaces() .InstancePerLifetimeScope() .EnableInterfaceInterceptors() .InterceptedBy(typeof(LogInterceptor));
每個RegisterAssemblyTypes()
調用將僅應用一組規則 - 如果要注冊多個不同組的組件,則需要多次調用RegisterAssemblyTypes()