.NET 切面編程 PostSharp

目錄

  • 概念
  • 實現方式
  • .Net平臺的切面實現
  • PostSharp示例

概念

  • Aspect-Oriented Programming(AOP):想一想OOP是否是有些熟悉,AOP翻譯過來的意思就是面向切面編程。先來關注一下涉及到的如下幾個概念點。
  • 橫切關注點: 存在於項目的絕大多數業務中能夠通用的一些輔助性的功能。例如日誌、安全、持久化等模塊。它們存在於核心業務代碼塊的各個地方,卻又獨立於這些核心業務邏輯。 如圖所示:
    Paste_Image.png
  • 切面: 這些橫切關注點的統一抽象。
  • 因此面向切面編程,就是將項目的輔助性功能(如日誌、異常處理、緩存處理等)與業務邏輯進行分離,把繁瑣的輔助性代碼抽離出來不用重複Copy,使得程序具有更高的模塊化。

實現方式

  • 靜態織入 即編譯時織入,實現原理是對編譯器作擴展,使得在代碼編譯時編譯器將切面代碼織入到指定的切點。
  • 動態織入 即運行時織入,編譯器在編譯時對切面代碼和業務代碼分別獨立編譯,而在運行的時候由CLR進行代碼混合。

.Net平臺的切面實現——PostSharp

  • 爲何選用PostSharp
    1. 輕量級的靜態織入實現(能夠經過反編譯清晰的知道你的代碼構成)
    2. 使用簡單,獨立編寫切面類,更好的實現模塊化,繼承自PostSharp提供的各類切面類型的抽象類,並重寫其中的攔截方法便可,能夠像使用類庫內置的Attribute那樣使用AOP
    3. 對調用方法有更多的控制點,好比輸入參數、返回結果、異常捕獲等
    4. 可是,可是自從2.0版本以後就難免費了
  • PostSharp的切面類
    1. OnMethodBoundaryAspect,針對方法內的各類可能存在切點的狀況進行代碼注入,實現切面思想,提供了OnEntry,OnExit,OnSuccess,OnException等可重寫的虛方法,顧名思義分別是在進入方法、退出方法、方法體成功執行、方法內發生異常的攔截。後續的實例是經過OnEntry來修改方法的輸入參數來展現的。
    2. OnFiledAccessAspect,對Filed的讀寫進行攔截處理,提供了OnGetValue,OnSetValue的虛方法。
    3. OnExceptionAspect,實現異常的捕獲。
    4. OnMethodInvocationAspect,方法調用攔截,提供OnInvocation虛方法。
    5. ImplementMethodAspect,用於extern方法、abstract類的方法進行攔截。
  • PostSharp的版本差別 3.0版本是個分水嶺,目前最新版本是5.0.28,他們的使用方式有一小點差別。
    • 3.0版本以前下載了安裝包,在項目中引用postsharp.dll,以後編碼就能夠了
    • 可是3.0以後是相似於VS插件的方式工做的,下載postsharp安裝包安裝以後會在vs的菜單中新增一個postsharp菜單(以下圖),能夠進行一些設置,在使用的時候再也不是引用,而是須要項目上右擊「添加postsharp到項目」

PostSharp示例

  1. 作前期準備工做,從PostSharp官網下載最新版本的安裝包,並安裝。
  2. 打開VisualStudio,新建解決方案,添加命令行項目。項目上右鍵後點擊「Add PostSharp to project」後在彈出窗口按提示操做,會發現已經多了postsharp的引用。
  3. 添加AspectAttribute切面類,實現對核心方法的輸入參數修改。須要注意的是postsharp提供的幾種切面類型都是繼承自Attribute基類,並且是經過對要實現攔截的類或方法添加特性的方式實現切面思想的。因此咱們的切面類 須要按照約定以xxxAttribute的格式命名。編程

    [Serializable]
      [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class AspectAttribute : OnMethodBoundaryAspect { //方法進入時 public override void OnEntry(MethodExecutionArgs args) { //修改輸入參數 args.Arguments[0] = "jingdong"; //設置方法是否繼續執行或退出,若設置的是FlowBehavior.Return方法會直接退出,不執行後續的全部代碼。 args.FlowBehavior = FlowBehavior.Continue; } //方法離開時 public override void OnExit(MethodExecutionArgs args) { Console.WriteLine("exit"); } //方法成功執行時 public override void OnSuccess(MethodExecutionArgs args) { Console.WriteLine("success"); } }
  4. 在program中添加咱們的核心方法Start,打印輸入參數。在須要實現攔截的方法添加上一個步驟中實現的切面類特性緩存

    public class Program { static void Main(string[] args) { var arg = "tmall"; Console.WriteLine($"original argument:{arg}"); Start(ref arg); Console.Read(); } [Aspect] static void Start(ref string arg) { Console.WriteLine($"real argument:{arg}"); Thread.Sleep(1000); Console.WriteLine("finished"); } }
  5. 由此就簡單經過postsharp實現了對方法的攔截,修改輸入參數,監聽方法成功執行以及退出。看下執行結果,成功的篡改了輸入參數,而且能夠看出攔截方法的方法體是先於OnSuccess執行的,OnSuccess的攔截執行完成以後纔是OnExit。
  6. 以前有說過postsharp是靜態織入來實現AOP編程的,那麼確定是經過編譯器在編譯的時候對代碼進行了織入,能夠經過反編譯exe文件來看下。

    能夠看到start方法被加入了若干行代碼。安全

  7. 有一個小點須要注意,使用postsharp的時候對切面類必須添加Serializable特性,不然在編譯的時候就會報錯。
  • 小結

    文章內的小例子主要是爲了說明postsharp實現AOP的基本原理,以及實現過程。並無如同實際項目中使用AOP來作一些日誌、安全、持久化之類的輔助功能。
相關文章
相關標籤/搜索