温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MSBuild + MSILInect实现编译时AOP之预览

发布时间:2020-05-21 10:13:39 阅读:521 作者:破狼 栏目:编程语言
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

在本文之前的前几篇浅谈.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

MSBuild + MSILInect实现编译时AOP之预览

1IMethodInjectInterface,拥有ExecuteingExceptionedExecuteSuccess三个契约为别为执行前,异常,成功。它们都有公同的参数类型:MethodExecutionEventArgs

  MSBuild + MSILInect实现编译时AOP之预览

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 : AttributeIMethodInject      {          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:

MatchedMethodInterceptBase:和上面方法之上的MethodInterceptBase大体一致,区别在于其应用于class之上,属性Rule为截获方法匹配(应用于多个方法之上相同截获),支持*匹配。
View Code      [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]       public class MatchedMethodInterceptBase : AttributeIMethodInject       {           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       }  复制代码 

3PropertyInterceptBase实现属性的注入,其属性Actionenum PropertyInterceptActionNone Get, Set)指注入属性的get或者SetView Code

 
其上默认都是Executeing继续执行,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(12, 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       }       }  复制代码 

注意测试有两种方式(由于没有安装包):

1:先重编译测试项目,运行ConsoleApplication2(在属性中修改控制台其实参数)。在查看测试项目。

2:将项目ConsoleApplication2修改为类库,在添加修改csprojec信息,Task位于Green.AOP.MyBuildTask,具体可以参见上一篇浅谈VS编译自定义编译任务—MSBuild Task(csproject)

在后续将会从简单Demo分析实现原理。

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]      public class PropertyInterceptBase : AttributeIMethodInject      {          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      }  复制代码 

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×