什麼是AOP?引用百度百科:AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。實現AOP主要由兩種方式,一種是編譯時靜態植入,優勢是效率高,缺點是缺少靈活性,.net下postsharp爲表明者(這個是收費的)。另外一種方式是動態代理,優缺點與前者相反,動態爲目標類型建立代理,經過代理調用實現攔截。AOP能作什麼,常見的用例是事務處理、日誌記錄等等。下面就講講Autofac怎麼實現AOP,Autofac是一個.net下很是優秀,性能很是好的IOC容器(.net下效率最高的容器),加上AOP簡直是如虎添翼。Autofac的AOP是經過Castle(也是一個容器)項目的核心部分實現的,名爲Autofac.Extras.DynamicProxy,顧名思義,其實現方式爲動態代理。
編程
使用前的準備:post
經過Nuget安裝程序包 :Autofac、Autofac.Extras.DynamicProxy,安裝成功以後會增長三個引用性能
下面正式開始了!測試
第一步:建立攔截器ui
下面是一個簡單的攔截器示例,該攔截器的功能是顯示被攔截的方法名稱、參數列表和返回結果spa
1 /// <summary> 2 /// 攔截器 須要實現 IInterceptor接口 Intercept方法 3 /// </summary> 4 public class CallLogger: IInterceptor 5 { 6 TextWriter _output; 7 8 public CallLogger(TextWriter output) 9 { 10 _output = output; 11 } 12 13 /// <summary> 14 /// 攔截方法 打印被攔截的方法執行前的名稱、參數和方法執行後的 返回結果 15 /// </summary> 16 /// <param name="invocation">包含被攔截方法的信息</param> 17 public void Intercept(IInvocation invocation) 18 { 19 20 _output.WriteLine("你正在調用方法 \"{0}\" 參數是 {1}... ", 21 invocation.Method.Name, 22 string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())); 23 24 //在被攔截的方法執行完畢後 繼續執行 25 invocation.Proceed(); 26 27 _output.WriteLine("方法執行完畢,返回結果:{0}", invocation.ReturnValue); 28 } 29 }
第二步:註冊攔截器到Autofac容器.net
攔截器必須註冊到Aufofac容器中,能夠經過攔截器類型或者命名注入,這兩種方式會讓使用攔截器的方法有所不一樣(後面會講到)。3d
1 // 命名注入 2 builder.Register(c => new CallLogger(Console.Out)) 3 .Named<IInterceptor>("log-calls"); 4 5 // 類型注入 6 builder.Register(c => new CallLogger(Console.Out));
第三步:啓用攔截器代理
啓用攔截器主要有兩個方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。日誌
EnableInterfaceInterceptors方法會動態建立一個接口代理
EnableClassInterceptors方法會建立一個目標類的子類代理類,這裏須要注意的是隻會攔截虛方法,重寫方法
啓用攔截器示例代碼:
//啓用類代理攔截 builder.RegisterType<Circle>().EnableClassInterceptors(); //啓用接口代理攔截 builder.RegisterType<Circle>().EnableInterfaceInterceptors();
第四步:指明要攔截的類型
有兩種方法:
第一種:給類型加上特性Attribute
第二種:在註冊類型到容器的時候動態注入攔截器
1 //動態注入攔截器CallLogger 2 builder.RegisterType<Circle>().InterceptedBy(typeof(CallLogger)).EnableClassInterceptors();
第五步:測試效果了
1.類代理攔截
Circle類代碼:
2.接口代理攔截
IShape接口代碼:
1 public interface IShape 2 { 3 /// <summary> 4 /// 形狀的面積 5 /// </summary> 6 void Area(); 7 8 }
Circle類代碼:
1 public class Circle:IShape 2 { 3 //重寫父類抽象方法 4 public void Area() 5 { 6 Console.WriteLine("你正在調用圓求面積的方法"); 7 } 8 }
若是有什麼地方寫得不對歡迎批評改正,若是有什麼疑問,歡迎提問。