什麼是AOP?引用百度百科:AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期動態代理實現程式功能的統一維護的一種技術。實現AOP主要由兩種方式,一種是編譯時靜態植入,優點是效率高,缺點是缺乏靈活性,.net下postsharp為代表者( ...
什麼是AOP?引用百度百科:AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期動態代理實現程式功能的統一維護的一種技術。實現AOP主要由兩種方式,一種是編譯時靜態植入,優點是效率高,缺點是缺乏靈活性,.net下postsharp為代表者(這個是收費的)。另一種方式是動態代理,優缺點與前者相反,動態為目標類型創建代理,通過代理調用實現攔截。AOP能做什麼,常見的用例是事務處理、日誌記錄等等。下麵就講講Autofac怎麼實現AOP,Autofac是一個.net下非常優秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP簡直是如虎添翼。Autofac的AOP是通過Castle(也是一個容器)項目的核心部分實現的,名為Autofac.Extras.DynamicProxy,顧名思義,其實現方式為動態代理。
使用前的準備:
通過Nuge安裝程式包 :Autofac、Autofac.Extras.DynamicProxy,安裝成功之後會增加三個引用
下麵正式開始了!
第一步:創建攔截器
下麵是一個簡單的攔截器示例,該攔截器的功能是顯示被攔截的方法名稱、參數列表和返回結果
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容器
攔截器必須註冊到Aufofac容器中,可以通過攔截器類型或者命名註入,這兩種方式會讓使用攔截器的方法有所不同(後面會講到)。
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 }
如果有什麼地方寫得不對歡迎批評改正,如果有什麼疑問,歡迎提問。