在本文之前的前幾篇淺談.NET編譯時注入(C#-->IL)、淺談VS編譯自定義編譯任務—MSBuild Task(csproject)、編譯時MSIL注入--實踐Mono Cecil(1)已經討論了MSBuild和Mono.Cicel。在這里我們將會利用它來實現一個簡單的編譯時AOP注入機制(這里所說的編譯時是指c#到MSIL的預編譯過程)。我更傾向于像EL(微軟企業庫框架)這類動態AOP。編譯時AOP有PostSharp這種被稱之為靜態AOP框架,其優勢在于直接代碼語句,性能更好,它不需要我們多余的代碼,像EL這種動態AOP,一般我們是不能直接new一個對象,需要容器(Container),在一些你的框架應用種,有時就需要使用者了解,再入我們對于WinForm、WebForm等.net平臺上主流的基于微軟事件機制的框架,事件方法的截獲,往往我們需要改變、包裝。在這時靜態AOP就顯出了他的優勢。
Class Diagram:
1:IMethodInject:Interface,擁有Executeing,Exceptioned,ExecuteSuccess三個契約為別為執行前,異常,成功。它們都有公同的參數類型:MethodExecutionEventArgs
Executeing:返回值為bool類型,將決定是否繼續執行方法體。Exceptioned:屬性Eeption代表發生的異常信息,返回值ExceptionStrategy(取值:Handle, ReThrow, ThrowNew)決定異常處理機制,Handle已處理并忽略,ReThrow重新拋出,ThrowNew拋出一個包裝后的來源于MethodExecutionEventArgs 的Exception。ExecuteSuccess,對于擁有返回值的方法,可以修改MethodExecutionEventArgs 的ReturnValue,修改返回值。最后MethodExecutionEventArgs的Order決定多個Attribute的注入先后,即方法截獲的先后順序。
1:MethodInterceptBase:針對于方法Attribute標簽,實現方法截獲View Code
- [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
- public class MethodInterceptBase : Attribute, IMethodInject
- {
- public int Order
- {
- get;
- set;
- }
- #region IMethodInject Members
- public virtual bool Executeing(MethodExecutionEventArgs args)
- {
- return true;
- }
- public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
- {
- return ExceptionStrategy.ReThrow;
- }
- public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
- {
- }
- #endregion
- }
- 復制代碼
2:
- View Code
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
- public class MatchedMethodInterceptBase : Attribute, IMethodInject
- {
- public int Order
- {
- get;
- set;
- }
- public string Rule
- {
- get;
- set;
- }
- #region IMethodInject Members
- public virtual bool Executeing(MethodExecutionEventArgs args)
- {
- return true;
- }
- public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
- {
- return ExceptionStrategy.ReThrow;
- }
- public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
- {
- }
- #endregion
- }
- 復制代碼
3:PropertyInterceptBase:實現屬性的注入,其屬性Action(enum PropertyInterceptAction:None Get, Set)指注入屬性的get或者Set;View Code
下面是一個簡單測試Code:
其上默認都是Executeing繼續執行,Exceptioned為拋出不處理,成功不修改result。
注意測試有兩種方式(由于沒有安裝包):
1:先重編譯測試項目,運行ConsoleApplication2(在屬性中修改控制臺其實參數)。在查看測試項目。
2:將項目ConsoleApplication2修改為類庫,在添加修改csprojec信息,Task位于Green.AOP.MyBuildTask,具體可以參見上一篇淺談VS編譯自定義編譯任務—MSBuild Task(csproject)。
在后續將會從簡單Demo分析實現原理。
- [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
- public class PropertyInterceptBase : Attribute, IMethodInject
- {
- public PropertyInterceptAction Action
- {
- get;
- set;
- }
- public int Order
- {
- get;
- set;
- }
- #region IMethodInject Members
- public virtual bool Executeing(MethodExecutionEventArgs args)
- {
- return true;
- }
- public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
- {
- return ExceptionStrategy.ReThrow;
- }
- public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
- {
- }
- #endregion
- }
- 復制代碼
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。