MSBuild + MSILInect实现编译时AOP之预览
在本文之前的前几篇浅谈.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)] publicclassMethodInterceptBase:Attribute,IMethodInject { publicintOrder{ get; set; } #regionIMethodInjectMembers publicvirtualboolExecuteing(MethodExecutionEventArgsargs) { returntrue; } publicvirtualExceptionStrategyExceptioned(MethodExecutionEventArgsargs) { returnExceptionStrategy.ReThrow; } publicvirtualvoidExecuteSuccess(MethodExecutionEventArgsargs) { } #endregion } 复制代码
2:MatchedMethodInterceptBase:和上面方法之上的MethodInterceptBase大体一致,区别在于其应用于class之上,属性Rule为截获方法匹配(应用于多个方法之上相同截获),支持*匹配。
ViewCode [AttributeUsage(AttributeTargets.Class,Inherited=false,AllowMultiple=false)] publicclassMatchedMethodInterceptBase:Attribute,IMethodInject { publicintOrder{ get; set; } publicstringRule{ get; set; } #regionIMethodInjectMembers publicvirtualboolExecuteing(MethodExecutionEventArgsargs) { returntrue; } publicvirtualExceptionStrategyExceptioned(MethodExecutionEventArgsargs) { returnExceptionStrategy.ReThrow; } publicvirtualvoidExecuteSuccess(MethodExecutionEventArgsargs) { } #endregion } 复制代码
3:PropertyInterceptBase:实现属性的注入,其属性Action(enum PropertyInterceptAction:None Get, Set)指注入属性的get或者Set;View Code
其上默认都是Executeing继续执行,Exceptioned为抛出不处理,成功不修改result。
下面是一个简单测试Code:
ViewCode usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Reflection; usingGreen.AOP; namespaceTest { //[TestAOP2Attribute(Rule="TestMethod1*")] publicclassClass1 { //[TestAOPPropertyAttribute(Action=PropertyInterceptAction.Set)] [TestAOPPropertyGetAttribute(Action=PropertyInterceptAction.Get)] publictestStrustTestProperty { get; set; } [Obsolete()] publicstaticvoidMain(string[]args) { try { vary=newClass1(); //y.TestProperty=DateTime.Now; Console.WriteLine(y.TestProperty); } catch(Exceptionex) { Console.WriteLine(ex.ToString()); } //newClass1().TestMethod1(1,2,null); Console.Read(); //thrownewException("exfffffffffffffffffffff"); } //[TestAOPAttribute(Order=1)] //[TestAOP1Attribute(TestProperty=1,Template="sdsdsd",Order=0)] publicClass1TestMethod1(inti,intj,Class1c) { Console.WriteLine("ok"); returnnewClass1(); } } publicclassTestAOPPropertyGetAttribute:Green.AOP.PropertyInterceptBase { #regionIMethodInjectMembers publicoverrideboolExecuteing(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine("------------------"+args); Console.WriteLine(args.Instance); Console.WriteLine(args.Method); Console.WriteLine(this.GetType()+":"+"Executeing"); returntrue; } publicoverrideGreen.AOP.ExceptionStrategyExceptioned(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Exceptioned"); returnGreen.AOP.ExceptionStrategy.ReThrow; } publicoverridevoidExecuteSuccess(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine("-----------"); Console.WriteLine(this.GetType()+":"+"ExecuteSuccess"+"--result:"+args.ReturnValue); } #endregion } publicclassTestAOPPropertyAttribute:Green.AOP.PropertyInterceptBase { #regionIMethodInjectMembers publicoverrideboolExecuteing(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(args.Instance); Console.WriteLine(args.Method); Console.WriteLine(this.GetType()+":"+"Executeing"); returntrue; } publicoverrideGreen.AOP.ExceptionStrategyExceptioned(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Exceptioned"); returnGreen.AOP.ExceptionStrategy.Handle; } publicoverridevoidExecuteSuccess(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"ExecuteSuccess"); } #endregion } publicclassTestAOP2Attribute:Green.AOP.MatchedMethodInterceptBase { #regionIMethodInjectMembers publicoverrideboolExecuteing(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(args.Instance); Console.WriteLine(args.Method); Console.WriteLine(this.GetType()+":"+"Executeing"); returntrue; } publicoverrideGreen.AOP.ExceptionStrategyExceptioned(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Exceptioned"); returnGreen.AOP.ExceptionStrategy.Handle; } publicoverridevoidExecuteSuccess(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"ExecuteSuccess"); } #endregion #regionIMethodInjectMembers publicboolMatch(System.Reflection.MethodBasemethod) { returntrue; } #endregion } //[AttributeUsage(AttributeTargets.Method)] publicclassTestAOPAttribute:Green.AOP.MethodInterceptBase { #regionIMethodInjectMembers publicoverrideboolExecuteing(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Executeing"); returntrue; } publicoverrideGreen.AOP.ExceptionStrategyExceptioned(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Exceptioned"); returnGreen.AOP.ExceptionStrategy.Handle; } publicoverridevoidExecuteSuccess(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"ExecuteSuccess"); } #endregion #regionIMethodInjectMembers publicboolMatch(System.Reflection.MethodBasemethod) { returntrue; } #endregion } [AttributeUsage(AttributeTargets.Method)] publicclassTestAOP1Attribute:Attribute,Green.AOP.IMethodInject { publicintOrder{ get; set; } publicintTestProperty { get; set; } publicstringTemplate { get; set; } #regionIMethodInjectMembers publicboolExecuteing(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Executeing"); returntrue; } publicGreen.AOP.ExceptionStrategyExceptioned(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"Exceptioned"); returnGreen.AOP.ExceptionStrategy.Handle; } publicvoidExecuteSuccess(Green.AOP.MethodExecutionEventArgsargs) { Console.WriteLine(this.GetType()+":"+"ExecuteSuccess"); } #endregion #regionIMethodInjectMembers publicboolMatch(System.Reflection.MethodBasemethod) { returntrue; } #endregion } } 复制代码
注意测试有两种方式(由于没有安装包):
1:先重编译测试项目,运行ConsoleApplication2(在属性中修改控制台其实参数)。在查看测试项目。
2:将项目ConsoleApplication2修改为类库,在添加修改csprojec信息,Task位于Green.AOP.MyBuildTask,具体可以参见上一篇浅谈VS编译自定义编译任务—MSBuild Task(csproject)。
在后续将会从简单Demo分析实现原理。
[AttributeUsage(AttributeTargets.Property,Inherited=false,AllowMultiple=false)] publicclassPropertyInterceptBase:Attribute,IMethodInject { publicPropertyInterceptActionAction{ get; set; } publicintOrder{ get; set; } #regionIMethodInjectMembers publicvirtualboolExecuteing(MethodExecutionEventArgsargs) { returntrue; } publicvirtualExceptionStrategyExceptioned(MethodExecutionEventArgsargs) { returnExceptionStrategy.ReThrow; } publicvirtualvoidExecuteSuccess(MethodExecutionEventArgsargs) { } #endregion } 复制代码
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。