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

1IMethodInjectInterface,拥有ExecuteingExceptionedExecuteSuccess三个契约为别为执行前,异常,成功。它们都有公同的参数类型: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


 
 
  1. [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]  
  2.     public class MethodInterceptBase : Attribute, IMethodInject  
  3.     {  
  4.         public int Order 
  5.         {  
  6.             get;  
  7.             set;  
  8.         }  
  9.         #region IMethodInject Members  
  10.  
  11.         public virtual bool Executeing(MethodExecutionEventArgs args)  
  12.         {  
  13.             return true;  
  14.         }  
  15.  
  16.         public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)  
  17.         {  
  18.             return ExceptionStrategy.ReThrow;  
  19.         }  
  20.  
  21.         public virtual void ExecuteSuccess(MethodExecutionEventArgs args)  
  22.         {  
  23.  
  24.         }  
  25.          
  26.         #endregion  
  27. }  
  28. 复制代码 

 

2:

MatchedMethodInterceptBase:和上面方法之上的MethodInterceptBase大体一致,区别在于其应用于class之上,属性Rule为截获方法匹配(应用于多个方法之上相同截获),支持*匹配。

 

 


 
 
  1. View Code   
  2.    
  3. [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]  
  4.  
  5.     public class MatchedMethodInterceptBase : Attribute, IMethodInject  
  6.  
  7.     {  
  8.  
  9.         public int Order 
  10.  
  11.         {  
  12.  
  13.             get;  
  14.  
  15.             set;  
  16.  
  17.         }  
  18.  
  19.    
  20.  
  21.         public string Rule 
  22.  
  23.         {  
  24.  
  25.             get;  
  26.  
  27.             set;  
  28.  
  29.         }  
  30.  
  31.         #region IMethodInject Members  
  32.  
  33.  
  34.         public virtual bool Executeing(MethodExecutionEventArgs args)  
  35.  
  36.         {  
  37.  
  38.             return true;  
  39.  
  40.         }  
  41.    
  42.  
  43.         public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)  
  44.  
  45.         {  
  46.  
  47.             return ExceptionStrategy.ReThrow;  
  48.  
  49.         }  
  50.  
  51.    
  52.  
  53.         public virtual void ExecuteSuccess(MethodExecutionEventArgs args)  
  54.  
  55.         {  
  56.  
  57.    
  58.  
  59.         }  
  60.  
  61.          
  62.  
  63.         #endregion  
  64.  
  65.     }  
  66. 复制代码 

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

 
其上默认都是Executeing继续执行,Exceptioned为抛出不处理,成功不修改result。

下面是一个简单测试Code:


  
  
  1. View Code   
  2.  
  3. using System;  
  4.  
  5. using System.Collections.Generic;  
  6.  
  7. using System.Linq;  
  8.  
  9. using System.Text;  
  10.  
  11. using System.Reflection;  
  12.  
  13. using Green.AOP;  
  14.  
  15.    
  16.  
  17. namespace Test  
  18.  
  19. {     
  20.  
  21.     // [TestAOP2Attribute(Rule = "TestMethod1*")]  
  22.  
  23.     public class Class1  
  24.  
  25.     {  
  26.  
  27.         // [TestAOPPropertyAttribute(Action = PropertyInterceptAction.Set)]  
  28.  
  29.         [TestAOPPropertyGetAttribute(Action = PropertyInterceptAction.Get)]  
  30.  
  31.         public testStrust TestProperty  
  32.  
  33.         {  
  34.  
  35.             get;  
  36.  
  37.             set;  
  38.  
  39.         }  
  40.  
  41.         [Obsolete()]  
  42.  
  43.         public static void Main(string[] args)  
  44.  
  45.         {            
  46.  
  47.             try  
  48.  
  49.             {  
  50.  
  51.                 var y = new Class1();  
  52.  
  53.                 // y.TestProperty = DateTime.Now;  
  54.  
  55.                 Console.WriteLine(y.TestProperty);  
  56.  
  57.             }  
  58.  
  59.             catch (Exception ex)  
  60.  
  61.             {  
  62.  
  63.                 Console.WriteLine(ex.ToString());  
  64.  
  65.             }  
  66.  
  67.             // new Class1().TestMethod1(1, 2, null);  
  68.  
  69.             Console.Read();  
  70.  
  71.             //throw new Exception("exfffffffffffffffffffff");  
  72.  
  73.         }  
  74.  
  75.         //[TestAOPAttribute(Order=1)]  
  76.  
  77.         //[TestAOP1Attribute(TestProperty = 1, Template = "sdsdsd",Order=0)]  
  78.  
  79.         public Class1 TestMethod1(int i, int j, Class1 c)  
  80.  
  81.         {  
  82.  
  83.             Console.WriteLine("ok");  
  84.  
  85.             return new Class1();  
  86.  
  87.         }  
  88.  
  89.     }  
  90.  
  91.     public class TestAOPPropertyGetAttribute : Green.AOP.PropertyInterceptBase  
  92.  
  93.     {  
  94.  
  95.         #region IMethodInject Members  
  96.  
  97.         public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)  
  98.  
  99.         {  
  100.  
  101.             Console.WriteLine("------------------" + args);  
  102.  
  103.             Console.WriteLine(args.Instance);  
  104.  
  105.             Console.WriteLine(args.Method);  
  106.  
  107.             Console.WriteLine(this.GetType() + ":" + "Executeing");  
  108.  
  109.             return true;  
  110.  
  111.         }  
  112.  
  113.         public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)  
  114.  
  115.         {  
  116.  
  117.             Console.WriteLine(this.GetType() + ":" + "Exceptioned");  
  118.  
  119.             return Green.AOP.ExceptionStrategy.ReThrow;  
  120.  
  121.         }  
  122.  
  123.         public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)  
  124.  
  125.         {  
  126.  
  127.             Console.WriteLine("-----------");  
  128.  
  129.             Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess" + "--result:" + args.ReturnValue);  
  130.  
  131.         }  
  132.  
  133.         #endregion  
  134.  
  135.     }  
  136.  
  137.     public class TestAOPPropertyAttribute : Green.AOP.PropertyInterceptBase  
  138.  
  139.     {  
  140.  
  141.         #region IMethodInject Members  
  142.  
  143.         public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)  
  144.  
  145.         {  
  146.  
  147.             Console.WriteLine(args.Instance);  
  148.  
  149.             Console.WriteLine(args.Method);  
  150.  
  151.             Console.WriteLine(this.GetType() + ":" + "Executeing");  
  152.  
  153.             return true;  
  154.  
  155.         }  
  156.  
  157.         public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)  
  158.  
  159.         {  
  160.  
  161.             Console.WriteLine(this.GetType() + ":" + "Exceptioned");  
  162.  
  163.             return Green.AOP.ExceptionStrategy.Handle;  
  164.  
  165.         }  
  166.  
  167.         public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)  
  168.  
  169.        {  
  170.  
  171.             Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");  
  172.  
  173.         }  
  174.  
  175.         #endregion  
  176.  
  177.     }  
  178.  
  179.     public class TestAOP2Attribute : Green.AOP.MatchedMethodInterceptBase  
  180.  
  181.     {  
  182.  
  183.         #region IMethodInject Members  
  184.  
  185.         public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)  
  186.  
  187.         {  
  188.  
  189.             Console.WriteLine(args.Instance);  
  190.  
  191.             Console.WriteLine(args.Method);  
  192.  
  193.             Console.WriteLine(this.GetType() + ":" + "Executeing");  
  194.  
  195.             return true;  
  196.  
  197.         }  
  198.  
  199.         public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)  
  200.  
  201.         {  
  202.  
  203.             Console.WriteLine(this.GetType() + ":" + "Exceptioned");  
  204.  
  205.             return Green.AOP.ExceptionStrategy.Handle;  
  206.  
  207.         }  
  208.  
  209.         public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)  
  210.  
  211.         {  
  212.  
  213.             Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");  
  214.  
  215.         }  
  216.  
  217.         #endregion  
  218.  
  219.         #region IMethodInject Members  
  220.  
  221.         public bool Match(System.Reflection.MethodBase method)  
  222.  
  223.         {  
  224.  
  225.             return true;  
  226.  
  227.         }  
  228.  
  229.         #endregion  
  230.  
  231.     }  
  232.  
  233.    
  234.  
  235.     //[AttributeUsage(AttributeTargets.Method)]  
  236.  
  237.     public class TestAOPAttribute : Green.AOP.MethodInterceptBase  
  238.  
  239.     {  
  240.  
  241.         #region IMethodInject Members  
  242.  
  243.         public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)  
  244.  
  245.         {  
  246.  
  247.             Console.WriteLine(this.GetType() + ":" + "Executeing");  
  248.  
  249.             return true;  
  250.  
  251.         }  
  252.  
  253.    
  254.  
  255.         public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)  
  256.  
  257.         {  
  258.  
  259.             Console.WriteLine(this.GetType() + ":" + "Exceptioned");  
  260.  
  261.             return Green.AOP.ExceptionStrategy.Handle;  
  262.  
  263.         }  
  264.  
  265.    
  266.  
  267.         public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)  
  268.  
  269.         {  
  270.  
  271.             Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");  
  272.  
  273.         }  
  274.  
  275.    
  276.  
  277.         #endregion  
  278.  
  279.    
  280.  
  281.         #region IMethodInject Members  
  282.  
  283.    
  284.  
  285.    
  286.  
  287.         public bool Match(System.Reflection.MethodBase method)  
  288.  
  289.         {  
  290.  
  291.             return true;  
  292.  
  293.         }  
  294.  
  295.    
  296.  
  297.         #endregion  
  298.  
  299.     }  
  300.  
  301.    
  302.  
  303.     [AttributeUsage(AttributeTargets.Method)]  
  304.  
  305.     public class TestAOP1Attribute : Attribute, Green.AOP.IMethodInject  
  306.  
  307.     {  
  308.  
  309.         public int Order 
  310.  
  311.         {  
  312.  
  313.             get;  
  314.  
  315.             set;  
  316.  
  317.         }  
  318.  
  319.    
  320.  
  321.         public int TestProperty  
  322.  
  323.         {  
  324.  
  325.             get;  
  326.  
  327.             set;  
  328.  
  329.         }  
  330.  
  331.    
  332.  
  333.         public string Template  
  334.  
  335.         {  
  336.  
  337.             get;  
  338.  
  339.             set;  
  340.  
  341.         }  
  342.  
  343.    
  344.  
  345.         #region IMethodInject Members  
  346.  
  347.    
  348.  
  349.         public bool Executeing(Green.AOP.MethodExecutionEventArgs args)  
  350.  
  351.         {  
  352.  
  353.             Console.WriteLine(this.GetType() + ":" + "Executeing");  
  354.  
  355.             return true;  
  356.  
  357.         }  
  358.  
  359.    
  360.  
  361.         public Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)  
  362.  
  363.         {  
  364.  
  365.             Console.WriteLine(this.GetType() + ":" + "Exceptioned");  
  366.  
  367.             return Green.AOP.ExceptionStrategy.Handle;  
  368.  
  369.         }  
  370.  
  371.    
  372.  
  373.         public void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)  
  374.  
  375.         {  
  376.  
  377.             Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");  
  378.  
  379.         }  
  380.  
  381.    
  382.  
  383.         #endregion  
  384.  
  385.    
  386.  
  387.         #region IMethodInject Members  
  388.  
  389.    
  390.  
  391.    
  392.  
  393.         public bool Match(System.Reflection.MethodBase method)  
  394.  
  395.         {  
  396.  
  397.             return true;  
  398.  
  399.         }  
  400.  
  401.    
  402.  
  403.         #endregion  
  404.  
  405.     }  
  406.  
  407.    
  408.  
  409. }  
  410. 复制代码 

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

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

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

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


  
  
  1. [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]  
  2.     public class PropertyInterceptBase : Attribute, IMethodInject  
  3.     {  
  4.         public PropertyInterceptAction Action 
  5.         {  
  6.             get;  
  7.             set;  
  8.         }  
  9.  
  10.         public int Order 
  11.         {  
  12.             get;  
  13.             set;  
  14.         }  
  15.         #region IMethodInject Members  
  16.  
  17.         public virtual bool Executeing(MethodExecutionEventArgs args)  
  18.         {  
  19.             return true;  
  20.         }  
  21.  
  22.         public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)  
  23.         {  
  24.             return ExceptionStrategy.ReThrow;  
  25.         }  
  26.  
  27.         public virtual void ExecuteSuccess(MethodExecutionEventArgs args)  
  28.         {  
  29.  
  30.         }  
  31.  
  32.         #endregion  
  33.     }  
  34. 复制代码 






本文转自 破狼 51CTO博客,原文链接:http://blog.51cto.com/whitewolfblog/835181 ,如需转载请自行联系原作者

相关文章
|
XML 开发框架 Java
《Spring6核心源码解析》已完结,涵盖IOC容器、AOP切面、AOT预编译、SpringMVC,面试杠杠的!
全网首个全面解析Spring6核心源码的专栏,涵盖:IOC容器、AOP切面、声明式事务、AOT预编译和SpringMVC,让你从根本上彻底掌握Spring6核心技术。
528 1
《Spring6核心源码解析》已完结,涵盖IOC容器、AOP切面、AOT预编译、SpringMVC,面试杠杠的!
|
数据可视化 C# C++
使用基于Roslyn的编译时AOP框架
介绍如何通过使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题。 可以在项目编译时自动插入指定代码,从而避免在运行时带来的性能消耗。
358 0
使用基于Roslyn的编译时AOP框架
|
XML Java Android开发
【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术
【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术
243 0
【字节码插桩】Android 打包流程 | Android 中的字节码操作方式 | AOP 面向切面编程 | APT 编译时技术
|
3月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
64 1
|
28天前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
75 1
什么是AOP面向切面编程?怎么简单理解?
|
1月前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
59 5
|
2月前
|
Java 容器
AOP面向切面编程
AOP面向切面编程
43 0
|
3月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
【9月更文挑战第9天】AOP(面向切面编程)通过分离横切关注点提高模块化程度,如日志记录、事务管理等。Micronaut AOP基于动态代理机制,在应用启动时为带有特定注解的类生成代理对象,实现在运行时拦截方法调用并执行额外逻辑。通过简单示例展示了如何在不修改 `CalculatorService` 类的情况下记录 `add` 方法的参数和结果,仅需添加 `@Loggable` 注解即可。这不仅提高了代码的可维护性和可扩展性,还降低了引入新错误的风险。
48 13