热门IT资讯网

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

发表于:2024-11-30 作者:热门IT资讯网编辑
编辑最后更新 2024年11月30日,在本文之前的前几篇浅谈.NET编译时注入(C#-->IL)、浅谈VS编译自定义编译任务-MSBuild Task(csproject)、编译时MSIL注入--实践Mono Cecil(1)已经讨论了M

在本文之前的前几篇浅谈.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. public virtual bool Executeing(MethodExecutionEventArgs args)
  11. {
  12. return true;
  13. }
  14. public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
  15. {
  16. return ExceptionStrategy.ReThrow;
  17. }
  18. public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
  19. {
  20. }
  21. #endregion
  22. }
  23. 复制代码

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

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

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

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

下面是一个简单测试Code:

  1. View Code
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Reflection;
  7. using Green.AOP;
  8. namespace Test
  9. {
  10. // [TestAOP2Attribute(Rule = "TestMethod1*")]
  11. public class Class1
  12. {
  13. // [TestAOPPropertyAttribute(Action = PropertyInterceptAction.Set)]
  14. [TestAOPPropertyGetAttribute(Action = PropertyInterceptAction.Get)]
  15. public testStrust TestProperty
  16. {
  17. get;
  18. set;
  19. }
  20. [Obsolete()]
  21. public static void Main(string[] args)
  22. {
  23. try
  24. {
  25. var y = new Class1();
  26. // y.TestProperty = DateTime.Now;
  27. Console.WriteLine(y.TestProperty);
  28. }
  29. catch (Exception ex)
  30. {
  31. Console.WriteLine(ex.ToString());
  32. }
  33. // new Class1().TestMethod1(1, 2, null);
  34. Console.Read();
  35. //throw new Exception("exfffffffffffffffffffff");
  36. }
  37. //[TestAOPAttribute(Order=1)]
  38. //[TestAOP1Attribute(TestProperty = 1, Template = "sdsdsd",Order=0)]
  39. public Class1 TestMethod1(int i, int j, Class1 c)
  40. {
  41. Console.WriteLine("ok");
  42. return new Class1();
  43. }
  44. }
  45. public class TestAOPPropertyGetAttribute : Green.AOP.PropertyInterceptBase
  46. {
  47. #region IMethodInject Members
  48. public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
  49. {
  50. Console.WriteLine("------------------" + args);
  51. Console.WriteLine(args.Instance);
  52. Console.WriteLine(args.Method);
  53. Console.WriteLine(this.GetType() + ":" + "Executeing");
  54. return true;
  55. }
  56. public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
  57. {
  58. Console.WriteLine(this.GetType() + ":" + "Exceptioned");
  59. return Green.AOP.ExceptionStrategy.ReThrow;
  60. }
  61. public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
  62. {
  63. Console.WriteLine("-----------");
  64. Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess" + "--result:" + args.ReturnValue);
  65. }
  66. #endregion
  67. }
  68. public class TestAOPPropertyAttribute : Green.AOP.PropertyInterceptBase
  69. {
  70. #region IMethodInject Members
  71. public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
  72. {
  73. Console.WriteLine(args.Instance);
  74. Console.WriteLine(args.Method);
  75. Console.WriteLine(this.GetType() + ":" + "Executeing");
  76. return true;
  77. }
  78. public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
  79. {
  80. Console.WriteLine(this.GetType() + ":" + "Exceptioned");
  81. return Green.AOP.ExceptionStrategy.Handle;
  82. }
  83. public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
  84. {
  85. Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
  86. }
  87. #endregion
  88. }
  89. public class TestAOP2Attribute : Green.AOP.MatchedMethodInterceptBase
  90. {
  91. #region IMethodInject Members
  92. public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
  93. {
  94. Console.WriteLine(args.Instance);
  95. Console.WriteLine(args.Method);
  96. Console.WriteLine(this.GetType() + ":" + "Executeing");
  97. return true;
  98. }
  99. public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
  100. {
  101. Console.WriteLine(this.GetType() + ":" + "Exceptioned");
  102. return Green.AOP.ExceptionStrategy.Handle;
  103. }
  104. public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
  105. {
  106. Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
  107. }
  108. #endregion
  109. #region IMethodInject Members
  110. public bool Match(System.Reflection.MethodBase method)
  111. {
  112. return true;
  113. }
  114. #endregion
  115. }
  116. //[AttributeUsage(AttributeTargets.Method)]
  117. public class TestAOPAttribute : Green.AOP.MethodInterceptBase
  118. {
  119. #region IMethodInject Members
  120. public override bool Executeing(Green.AOP.MethodExecutionEventArgs args)
  121. {
  122. Console.WriteLine(this.GetType() + ":" + "Executeing");
  123. return true;
  124. }
  125. public override Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
  126. {
  127. Console.WriteLine(this.GetType() + ":" + "Exceptioned");
  128. return Green.AOP.ExceptionStrategy.Handle;
  129. }
  130. public override void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
  131. {
  132. Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
  133. }
  134. #endregion
  135. #region IMethodInject Members
  136. public bool Match(System.Reflection.MethodBase method)
  137. {
  138. return true;
  139. }
  140. #endregion
  141. }
  142. [AttributeUsage(AttributeTargets.Method)]
  143. public class TestAOP1Attribute : Attribute, Green.AOP.IMethodInject
  144. {
  145. public int Order
  146. {
  147. get;
  148. set;
  149. }
  150. public int TestProperty
  151. {
  152. get;
  153. set;
  154. }
  155. public string Template
  156. {
  157. get;
  158. set;
  159. }
  160. #region IMethodInject Members
  161. public bool Executeing(Green.AOP.MethodExecutionEventArgs args)
  162. {
  163. Console.WriteLine(this.GetType() + ":" + "Executeing");
  164. return true;
  165. }
  166. public Green.AOP.ExceptionStrategy Exceptioned(Green.AOP.MethodExecutionEventArgs args)
  167. {
  168. Console.WriteLine(this.GetType() + ":" + "Exceptioned");
  169. return Green.AOP.ExceptionStrategy.Handle;
  170. }
  171. public void ExecuteSuccess(Green.AOP.MethodExecutionEventArgs args)
  172. {
  173. Console.WriteLine(this.GetType() + ":" + "ExecuteSuccess");
  174. }
  175. #endregion
  176. #region IMethodInject Members
  177. public bool Match(System.Reflection.MethodBase method)
  178. {
  179. return true;
  180. }
  181. #endregion
  182. }
  183. }
  184. 复制代码

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

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. public int Order
  10. {
  11. get;
  12. set;
  13. }
  14. #region IMethodInject Members
  15. public virtual bool Executeing(MethodExecutionEventArgs args)
  16. {
  17. return true;
  18. }
  19. public virtual ExceptionStrategy Exceptioned(MethodExecutionEventArgs args)
  20. {
  21. return ExceptionStrategy.ReThrow;
  22. }
  23. public virtual void ExecuteSuccess(MethodExecutionEventArgs args)
  24. {
  25. }
  26. #endregion
  27. }
  28. 复制代码
0