/src/LinFu.AOP/Extensions/MethodCallInterceptionExtensions.cs

http://github.com/philiplaureano/LinFu · C# · 170 lines · 85 code · 14 blank · 71 comment · 1 complexity · aa3354bf4b463366d14c62fbaaff8296 MD5 · raw file

  1. using System;
  2. using System.Linq;
  3. using LinFu.AOP.Cecil.Interfaces;
  4. using LinFu.AOP.Interfaces;
  5. using Mono.Cecil;
  6. namespace LinFu.AOP.Cecil.Extensions
  7. {
  8. /// <summary>
  9. /// Represents an extension class that adds method call interception support to the Mono.Cecil object model.
  10. /// </summary>
  11. public static class MethodCallInterceptionExtensions
  12. {
  13. /// <summary>
  14. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  15. /// calls made inside the target.
  16. /// </summary>
  17. /// <param name="target">The target object.</param>
  18. public static void InterceptAllMethodCalls(this AssemblyDefinition target)
  19. {
  20. target.InterceptMethodCalls(GetDefaultTypeFilter());
  21. }
  22. /// <summary>
  23. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  24. /// calls made inside the target.
  25. /// </summary>
  26. /// <param name="target">The target object.</param>
  27. public static void InterceptAllMethodCalls(this TypeDefinition target)
  28. {
  29. var hostMethodFilter = GetHostMethodFilter();
  30. Func<MethodReference, bool> methodCallFilter = m => true;
  31. InterceptMethodCalls(target, GetDefaultTypeFilter(), hostMethodFilter, methodCallFilter);
  32. }
  33. /// <summary>
  34. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  35. /// calls made inside the target.
  36. /// </summary>
  37. /// <param name="target">The target object.</param>
  38. /// <param name="typeFilter">The type filter that determines which types will be modified for interception.</param>
  39. public static void InterceptMethodCalls(this AssemblyDefinition target,
  40. Func<TypeReference, bool> typeFilter)
  41. {
  42. var hostMethodFilter = GetHostMethodFilter();
  43. Func<MethodReference, bool> methodCallFilter = m => true;
  44. InterceptMethodCalls(target, typeFilter, hostMethodFilter, methodCallFilter);
  45. }
  46. /// <summary>
  47. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  48. /// calls made inside the target.
  49. /// </summary>
  50. /// <param name="target">The target object.</param>
  51. /// <param name="typeFilter">The type filter that determines the types that will be modified.</param>
  52. public static void InterceptMethodCalls(this TypeDefinition target, Func<TypeReference, bool> typeFilter)
  53. {
  54. var hostMethodFilter = GetHostMethodFilter();
  55. Func<MethodReference, bool> methodCallFilter = m => true;
  56. InterceptMethodCalls(target, typeFilter, hostMethodFilter, methodCallFilter);
  57. }
  58. /// <summary>
  59. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  60. /// calls made inside the target.
  61. /// </summary>
  62. /// <param name="target">The target object.</param>
  63. /// <param name="methodCallFilter">
  64. /// The <see cref="IMethodCallFilter" /> instance that determines the method calls that will
  65. /// be intercepted.
  66. /// </param>
  67. /// <param name="hostMethodFilter">
  68. /// The <see cref="IMethodFilter" /> instance that determines the host method calls that
  69. /// will be modified
  70. /// </param>
  71. public static void InterceptMethodCalls(this TypeDefinition target, IMethodCallFilter methodCallFilter,
  72. IMethodFilter hostMethodFilter)
  73. {
  74. var rewriter = new InterceptMethodCalls(methodCallFilter);
  75. target.Accept(new ImplementModifiableType(GetDefaultTypeFilter()));
  76. target.WeaveWith(rewriter);
  77. }
  78. /// <summary>
  79. /// Modifies the current <paramref name="target" /> to support third-party method call interception for all method
  80. /// calls made inside the target.
  81. /// </summary>
  82. /// <param name="target">The target object.</param>
  83. /// <param name="methodCallFilter">
  84. /// The <see cref="IMethodCallFilter" /> instance that determines the method calls that will
  85. /// be intercepted.
  86. /// </param>
  87. /// <param name="hostMethodFilter">
  88. /// The <see cref="IMethodFilter" /> instance that determines the host method calls that
  89. /// will be modified
  90. /// </param>
  91. public static void InterceptMethodCalls(this AssemblyDefinition target,
  92. IMethodCallFilter methodCallFilter,
  93. IMethodFilter hostMethodFilter)
  94. {
  95. var module = target.MainModule;
  96. var methods = module.Types.Where(t => GetDefaultTypeFilter()(t)).SelectMany(t => t.Methods)
  97. .Where(hostMethodFilter.ShouldWeave).ToArray();
  98. var rewriter = new InterceptMethodCalls(methodCallFilter);
  99. target.Accept(new ImplementModifiableType(GetDefaultTypeFilter()));
  100. target.WeaveWith(rewriter);
  101. }
  102. /// <summary>
  103. /// Modifies the current <paramref name="target" /> to support third-party method call interception.
  104. /// </summary>
  105. /// <param name="target">The target object.</param>
  106. /// <param name="typeFilter">The filter that will determine the target types that will be modified.</param>
  107. /// <param name="hostMethodFilter">The filter that will determine the methods that will be modified on the target type.</param>
  108. /// <param name="methodCallFilter">
  109. /// The filter that will determine which third-party methods will be intercepted on the
  110. /// target type.
  111. /// </param>
  112. public static void InterceptMethodCalls(this AssemblyDefinition target,
  113. Func<TypeReference, bool> typeFilter,
  114. Func<MethodReference, bool> hostMethodFilter,
  115. Func<MethodReference, bool> methodCallFilter)
  116. {
  117. var rewriter = new InterceptMethodCalls(hostMethodFilter, methodCallFilter);
  118. target.Accept(new ImplementModifiableType(typeFilter));
  119. target.WeaveWith(rewriter);
  120. }
  121. /// <summary>
  122. /// Modifies the current <paramref name="target" /> to support third-party method call interception.
  123. /// </summary>
  124. /// <param name="target">The target object.</param>
  125. /// <param name="typeFilter">The filter that will determine the target types that will be modified.</param>
  126. /// <param name="hostMethodFilter">The filter that will determine the methods that will be modified on the target type.</param>
  127. /// <param name="methodCallFilter">
  128. /// The filter that will determine which third-party methods will be intercepted on the
  129. /// target type.
  130. /// </param>
  131. public static void InterceptMethodCalls(this TypeDefinition target, Func<TypeReference, bool> typeFilter,
  132. Func<MethodReference, bool> hostMethodFilter,
  133. Func<MethodReference, bool> methodCallFilter)
  134. {
  135. var rewriter = new InterceptMethodCalls(hostMethodFilter, methodCallFilter);
  136. target.Accept(new ImplementModifiableType(typeFilter));
  137. target.WeaveWith(rewriter);
  138. }
  139. private static Func<TypeReference, bool> GetDefaultTypeFilter()
  140. {
  141. return type =>
  142. {
  143. var actualType1 = type.Resolve();
  144. return !actualType1.IsValueType && !actualType1.IsInterface;
  145. };
  146. }
  147. private static Func<MethodReference, bool> GetHostMethodFilter()
  148. {
  149. return method =>
  150. {
  151. var actualMethod = method.Resolve();
  152. return actualMethod.HasBody;
  153. };
  154. }
  155. }
  156. }