.NET 通過 Autofac 和 DynamicProxy 實現AOP


  什么是AOP?引用百度百科:AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。實現AOP主要由兩種方式,一種是編譯時靜態植入,優點是效率高,缺點是缺乏靈活性,.net下postsharp為代表者(這個是收費的)。另一種方式是動態代理,優缺點與前者相反,動態為目標類型創建代理,通過代理調用實現攔截。AOP能做什么,常見的用例是事務處理、日志記錄等等。下面就講講Autofac怎么實現AOP,Autofac是一個.net下非常優秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP簡直是如虎添翼。Autofac的AOP是通過Castle(也是一個容器)項目的核心部分實現的,名為Autofac.Extras.DynamicProxy,顧名思義,其實現方式為動態代理。

  使用前的准備:

    通過Nuget安裝程序包 :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     }

 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM