在本文之前的前幾篇淺談.NET編譯時注入(C#-->IL)、淺談VS編譯自定義編譯任務(wù)—MSBuild Task(csproject)、編譯時MSIL注入--實踐Mono Cecil(1)已經(jīng)討論了MSBuild和Mono.Cicel。在這里我們將會利用它來實現(xiàn)一個簡單的編譯時AOP注入機制(這里所說的編譯時是指c#到MSIL的預(yù)編譯過程)。我更傾向于像EL(微軟企業(yè)庫框架)這類動態(tài)AOP。編譯時AOP有PostSharp這種被稱之為靜態(tài)AOP框架,其優(yōu)勢在于直接代碼語句,性能更好,它不需要我們多余的代碼,像EL這種動態(tài)AOP,一般我們是不能直接new一個對象,需要容器(Container),在一些你的框架應(yīng)用種,有時就需要使用者了解,再入我們對于WinForm、WebForm等.net平臺上主流的基于微軟事件機制的框架,事件方法的截獲,往往我們需要改變、包裝。在這時靜態(tài)AOP就顯出了他的優(yōu)勢。
從事成都棕樹電信機房,服務(wù)器租用,云主機,網(wǎng)站空間,空間域名,CDN,網(wǎng)絡(luò)代維等服務(wù)。
Class Diagram:
1:IMethodInject:Interface,擁有Executeing,Exceptioned,ExecuteSuccess三個契約為別為執(zhí)行前,異常,成功。它們都有公同的參數(shù)類型:MethodExecutionEventArgs
Executeing:返回值為bool類型,將決定是否繼續(xù)執(zhí)行方法體。Exceptioned:屬性Eeption代表發(fā)生的異常信息,返回值ExceptionStrategy(取值:Handle, ReThrow, ThrowNew)決定異常處理機制,Handle已處理并忽略,ReThrow重新拋出,ThrowNew拋出一個包裝后的來源于MethodExecutionEventArgs 的Exception。ExecuteSuccess,對于擁有返回值的方法,可以修改MethodExecutionEventArgs 的ReturnValue,修改返回值。最后MethodExecutionEventArgs的Order決定多個Attribute的注入先后,即方法截獲的先后順序。
1:MethodInterceptBase:針對于方法Attribute標(biāo)簽,實現(xiàn)方法截獲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
- }
- 復(fù)制代碼
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
- }
- 復(fù)制代碼
3:PropertyInterceptBase:實現(xiàn)屬性的注入,其屬性Action(enum PropertyInterceptAction:None Get, Set)指注入屬性的get或者Set;View Code
其上默認(rèn)都是Executeing繼續(xù)執(zhí)行,Exceptioned為拋出不處理,成功不修改result。
下面是一個簡單測試Code:
- View Code
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Reflection;
- using Green.AOP;
- namespace Test
- {
- // [TestAOP2Attribute(Rule = "TestMethod1*")]
- public class Class1
- {
- // [TestAOPPropertyAttribute(Action = PropertyInterceptAction.Set)]
- [TestAOPPropertyGetAttribute(Action = PropertyInterceptAction.Get)]
- public testStrust TestProperty
- {
- get;
- set;
- }
- [Obsolete()]
- public static void Main(string[] args)
- {
- try
- {
- var y = new Class1();
- // y.TestProperty = DateTime.Now;
- Console.WriteLine(y.TestProperty);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.ToString());
- }
- // new Class1().TestMethod1(1, 2, null);
- Console.Read();
- //throw new Exception("exfffffffffffffffffffff");
- }
- //[TestAOPAttribute(Order=1)]
- //[TestAOP1Attribute(TestProperty = 1, Template = "sdsdsd",Order=0)]
- public Class1 TestMethod1(int i, int j, Class1 c)
- {
- Console.WriteLine("ok");
- return new Class1();
- }
- }
- public class TestAOPPropertyGetAttribute : Green.AOP.PropertyInterceptBase
- {
- #region IMethodInject Members
- public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine("------------------" + args);
- Console.WriteLine(args.Instance);
- Console.WriteLine(args.Method);
- Console.WriteLine(this.GetType() + ":" + "Executeing");
- return true;
- }
- public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Exceptioned");
- return Green.AOP.ExceptionStrategy.ReThrow;
- }
- public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine("-----------");
- Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess" + "--result:" + args.ReturnValue);
- }
- #endregion
- }
- public class TestAOPPropertyAttribute : Green.AOP.PropertyInterceptBase
- {
- #region IMethodInject Members
- public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(args.Instance);
- Console.WriteLine(args.Method);
- Console.WriteLine(this.GetType() + ":" + "Executeing");
- return true;
- }
- public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Exceptioned");
- return Green.AOP.ExceptionStrategy.Handle;
- }
- public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
- }
- #endregion
- }
- public class TestAOP2Attribute : Green.AOP.MatchedMethodInterceptBase
- {
- #region IMethodInject Members
- public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(args.Instance);
- Console.WriteLine(args.Method);
- Console.WriteLine(this.GetType() + ":" + "Executeing");
- return true;
- }
- public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Exceptioned");
- return Green.AOP.ExceptionStrategy.Handle;
- }
- public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
- }
- #endregion
- #region IMethodInject Members
- public bool Match(System.Reflection.MethodBase method)
- {
- return true;
- }
- #endregion
- }
- //[AttributeUsage(AttributeTargets.Method)]
- public class TestAOPAttribute : Green.AOP.MethodInterceptBase
- {
- #region IMethodInject Members
- public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Executeing");
- return true;
- }
- public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Exceptioned");
- return Green.AOP.ExceptionStrategy.Handle;
- }
- public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
- }
- #endregion
- #region IMethodInject Members
- public bool Match(System.Reflection.MethodBase method)
- {
- return true;
- }
- #endregion
- }
- [AttributeUsage(AttributeTargets.Method)]
- public class TestAOP1Attribute : Attribute, Green.AOP.IMethodInject
- {
- public int Order
- {
- get;
- set;
- }
- public int TestProperty
- {
- get;
- set;
- }
- public string Template
- {
- get;
- set;
- }
- #region IMethodInject Members
- public bool Executeing(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Executeing");
- return true;
- }
- public Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "Exceptioned");
- return Green.AOP.ExceptionStrategy.Handle;
- }
- public void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
- {
- Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
- }
- #endregion
- #region IMethodInject Members
- public bool Match(System.Reflection.MethodBase method)
- {
- return true;
- }
- #endregion
- }
- }
- 復(fù)制代碼
注意測試有兩種方式(由于沒有安裝包):
1:先重編譯測試項目,運行ConsoleApplication2(在屬性中修改控制臺其實參數(shù))。在查看測試項目。
2:將項目ConsoleApplication2修改為類庫,在添加修改csprojec信息,Task位于Green.AOP.MyBuildTask,具體可以參見上一篇淺談VS編譯自定義編譯任務(wù)—MSBuild Task(csproject)。
在后續(xù)將會從簡單Demo分析實現(xiàn)原理。
- [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
- }
- 復(fù)制代碼