PostSharp – Lightweight Aspect-Oriented System

來源:互聯網
上載者:User

PostSharp——開源的AOP架構 < PostSharp - Lightweight Aspect-Oriented System > 關於AOP...

PostSharp 是一個令人興奮的項目,他結合了 MSBuild Task 和 MSIL Injection 技術,從另外一個角度實現 AOP 編程。試用過後你會感覺到其便利性,我們和以往基於 Dynamic Proxy 方式的 AOP 解決方案做個比較。

    * 由於採用 MSIL Injection,因此靜態代碼注入的執行效率要高於使用 Reflection Emit。
    * 使用 MSBuild Task,使得開發人員可以像使用編譯器內建 Attribute 那樣使用 AOP。
    * 可以攔截任意方法,而 Dynamic Proxy 方式的 AOP 往往採取繼承方式來攔截 Virtual 方法。
    * 擁有更多的控制權。包括中斷執行流程,修改參數和傳回值等等。
    * 還可以攔截 Field Access、Exception 等操作。
    * 無需將對象建立代碼改成 "new proxy()",更加透明。
    * 可以使用萬用字元進行多重攔截匹配。
    * 靜態注入帶來的問題更多的是注入代碼的品質和調試複雜度。

我們寫一個簡單的例子,看看效果。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using PostSharp.Laos;

[Serializable]
public class AopMethodAttribute : OnMethodBoundaryAspect
{
  public override void OnEntry(MethodExecutionEventArgs eventArgs)
  {
    // 擷取方法名稱
    Console.WriteLine("OnEntry:{0}.{1}", eventArgs.Method.ReflectedType, eventArgs.Method);
   
    // 顯示方法參數
    ParameterInfo[] ps = eventArgs.Method.GetParameters();
    object[] pv = eventArgs.GetArguments();

    for (int i = 0; i < ps.Length; i++)
    {
      Console.WriteLine(" {0}={1}", ps[i].Name, pv[i]);
    }
  }

  public override void OnExit(MethodExecutionEventArgs eventArgs)
  {
    Console.WriteLine("OnExit...");
  }
}

public class MyClass
{
  [AopMethod]
  public int Test(int i)
  {
    Console.WriteLine("Test:{0}", i);
    return i++;
  }
}

MyClass o = new MyClass();
o.Test(123);

輸出:
OnEntry:MyClass.Int32 Test(Int32)
i=123
Test:123
OnExit...

整個過程非常簡單:
1. 建立一個繼承自 OnMethodBoundaryAspect 的屬性類別,用於攔截方法。
2. override 特定的方法,執行攔截操作。方法參數提供了各種操作能力。
3. 向目標方法添加特性。
4. 編譯,執行。

或許你會好奇,AopMethodAttribute 是如何被建立執行個體,並被執行的呢?

1. 注意編譯時間 VS2005 Output 視窗的輸出內容,你會看到如下內容。其實 PostSharp 提供了一個 MSBuild Task,在我們每次編譯時間會調用它執行一些注入操作。
PostSharp 1.0 [1.0.4.162] - Copyright (c) Gael Fraiteur and Community, 2006.

2. 用反編譯工具看看注入後的方法內容。看完這些代碼,就算我不說,你也能明白它是如何?攔截的了。
static MyClass()
{
  if (!~PostSharp~Laos~Implementation.initialized)
  {
    throw new LaosNotInitializedException();
  }
  ~PostSharp~Laos~Implementation.~targetMethod~1 = methodof(MyClass.Test);
  ~PostSharp~Laos~Implementation.~aspect~1.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~1);
}

public int Test(int i)
{
  int returnValue;
  MethodExecutionEventArgs eventArgs;
  try
  {
    object[] arguments = new object[] { i };
    eventArgs = new MethodExecutionEventArgs(methodof(MyClass.Test, MyClass), this, arguments);
    ~PostSharp~Laos~Implementation.~aspect~1.OnEntry(eventArgs);
    if (eventArgs.FlowBehavior == FlowBehavior.Return)
    {
      return (int) eventArgs.ReturnValue;
    }
    Console.WriteLine("Test:{0}", i);
    int num = i++;
    returnValue = num;
    eventArgs.ReturnValue = returnValue;
    ~PostSharp~Laos~Implementation.~aspect~1.OnSuccess(eventArgs);
    returnValue = (int) eventArgs.ReturnValue;
  }
  catch (Exception exception)
  {
    eventArgs.Exception = exception;
    ~PostSharp~Laos~Implementation.~aspect~1.OnException(eventArgs);
    switch (eventArgs.FlowBehavior)
    {
      case FlowBehavior.Continue:
        return returnValue;

      case FlowBehavior.Return:
        return (int) eventArgs.ReturnValue;
    }
    throw;
  }
  finally
  {
    eventArgs.ReturnValue = returnValue;
    ~PostSharp~Laos~Implementation.~aspect~1.OnExit(eventArgs);
    returnValue = (int) eventArgs.ReturnValue;
  }
  return returnValue;
}

我們可以使用萬用字元攔截更多的內容,以簡化我們的編碼。
[AopMethod(AttributeTargetMembers="T*")]
public class MyClass
{
  public int T1(int i)
  {
    Console.WriteLine("T1:{0}", i);
    return i++;
  }

  public void T2(string s)
  {
    Console.WriteLine("T2:{0}", s);
  }
}

我們繼續寫一點其它的例子,諸如攔截屬性訪問和異常。

Field Aspect
[Serializable]
public class AopPropertyAttribute : OnFieldAccessAspect
{
  public override void OnGetValue(FieldAccessEventArgs eventArgs)
  {
    Console.WriteLine("ExposedFieldValue:{0}; StoredFieldValue:{1}",
      eventArgs.ExposedFieldValue, eventArgs.StoredFieldValue);
  }

  public override void OnSetValue(FieldAccessEventArgs eventArgs)
  {
    Console.WriteLine("ExposedFieldValue:{0}; StoredFieldValue:{1}",
      eventArgs.ExposedFieldValue, eventArgs.StoredFieldValue);
  }
}

public class MyClass
{
  [AopProperty]
  private int x;

  public int X
  {
    get { return x; }
    set { x = value; }
  }
}

Exception Aspect
[Serializable]
public class AopExceptionAttribute : OnExceptionAspect
{
  public override void OnException(MethodExecutionEventArgs eventArgs)
  {
    Console.WriteLine(eventArgs.Exception.Message);
    eventArgs.FlowBehavior = FlowBehavior.Return;
  }
}

public class MyClass
{
  [AopException]
  public void Test(int i)
  {
    throw new Exception("Error...");
  }
}

更詳細的資訊,請訪問 PostSharp 網站,或者查閱其協助檔案。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.