1. 程式人生 > >.NET 通過 Autofac 和 DynamicProxy 實現AOP

.NET 通過 Autofac 和 DynamicProxy 實現AOP

調用方法 console mage 技術分享 攔截器 抽象 select 攔截 bsp

  什麽是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     }

    如果有什麽地方寫得不對歡迎批評改正,如果有什麽疑問,歡迎提問。

.NET 通過 Autofac 和 DynamicProxy 實現AOP