/src/LinFu.AOP/Extensions/FieldInterceptionExtensions.cs

http://github.com/philiplaureano/LinFu · C# · 180 lines · 109 code · 20 blank · 51 comment · 3 complexity · 759fa863e8db0ef727ee863d1edd504b MD5 · raw file

  1. using System;
  2. using System.Linq;
  3. using LinFu.AOP.Cecil.Interfaces;
  4. using LinFu.AOP.Interfaces;
  5. using LinFu.Reflection.Emit;
  6. using Mono.Cecil;
  7. namespace LinFu.AOP.Cecil.Extensions
  8. {
  9. /// <summary>
  10. /// Represents an extension class that adds field interception support to a given type.
  11. /// </summary>
  12. public static class FieldInterceptionExtensions
  13. {
  14. /// <summary>
  15. /// Adds field interception support to the target type.
  16. /// </summary>
  17. /// <param name="targetType">The type that will be modified.</param>
  18. public static void InterceptAllFields(this AssemblyDefinition targetType)
  19. {
  20. var methodFilter = GetMethodFilter();
  21. targetType.InterceptFields(methodFilter, f => true);
  22. }
  23. /// <summary>
  24. /// Adds field interception support intercepting all instance fields on the target type.
  25. /// </summary>
  26. /// <param name="targetType">The type that will be modified.</param>
  27. public static void InterceptAllInstanceFields(this AssemblyDefinition targetType)
  28. {
  29. var methodFilter = GetMethodFilter();
  30. var fieldFilter = GetFieldFilter(f => !f.IsStatic);
  31. targetType.InterceptFields(methodFilter, fieldFilter);
  32. }
  33. /// <summary>
  34. /// Adds field interception support intercepting all static fields on the target type.
  35. /// </summary>
  36. /// <param name="targetType">The type that will be modified.</param>
  37. public static void InterceptAllStaticFields(this AssemblyDefinition targetType)
  38. {
  39. var methodFilter = GetMethodFilter();
  40. var fieldFilter = GetFieldFilter(f => f.IsStatic);
  41. targetType.InterceptFields(methodFilter, fieldFilter);
  42. }
  43. /// <summary>
  44. /// Adds field interception support to the target type.
  45. /// </summary>
  46. /// <param name="targetType">The type that will be modified.</param>
  47. public static void InterceptAllFields(this TypeDefinition targetType)
  48. {
  49. var methodFilter = GetMethodFilter();
  50. targetType.InterceptFields(methodFilter, f => true);
  51. }
  52. /// <summary>
  53. /// Adds field interception support intercepting all instance fields on the target type.
  54. /// </summary>
  55. /// <param name="targetType">The type that will be modified.</param>
  56. public static void InterceptAllInstanceFields(this TypeDefinition targetType)
  57. {
  58. var methodFilter = GetMethodFilter();
  59. var fieldFilter = GetFieldFilter(f => !f.IsStatic);
  60. targetType.InterceptFields(methodFilter, fieldFilter);
  61. }
  62. /// <summary>
  63. /// Adds field interception support intercepting all static fields on the target type.
  64. /// </summary>
  65. /// <param name="targetType">The type that will be modified.</param>
  66. public static void InterceptAllStaticFields(this TypeDefinition targetType)
  67. {
  68. var methodFilter = GetMethodFilter();
  69. var fieldFilter = GetFieldFilter(actualField => actualField.IsStatic);
  70. targetType.InterceptFields(methodFilter, fieldFilter);
  71. }
  72. /// <summary>
  73. /// Adds field interception support to the target type.
  74. /// </summary>
  75. /// <param name="targetType">The type that will be modified.</param>
  76. /// <param name="methodFilter">
  77. /// The filter that determines which methods on the target type will be modified to support
  78. /// field interception.
  79. /// </param>
  80. /// <param name="fieldFilter">The filter that determines which fields should be intercepted.</param>
  81. public static void InterceptFields(this TypeDefinition targetType,
  82. Func<MethodReference, bool> methodFilter,
  83. Func<FieldReference, bool> fieldFilter)
  84. {
  85. var typeWeaver = new ImplementFieldInterceptionHostWeaver(t => true);
  86. var fieldWeaver = new InterceptFieldAccess(fieldFilter);
  87. typeWeaver.Weave(targetType);
  88. var targetMethods = targetType.Methods.Where(m => methodFilter(m)).ToArray();
  89. foreach (var method in targetMethods)
  90. {
  91. fieldWeaver.Rewrite(method, method.GetILGenerator(), method.Body.Instructions.ToArray());
  92. }
  93. }
  94. /// <summary>
  95. /// Adds field interception support to the target type.
  96. /// </summary>
  97. /// <param name="targetAssembly">The type that will be modified.</param>
  98. /// <param name="hostTypeFilter">The filter that determines the host types to be modified.</param>
  99. /// <param name="fieldFilter">The field filter that determines the fields that will be intercepted.</param>
  100. public static void InterceptFields(this AssemblyDefinition targetAssembly, ITypeFilter hostTypeFilter,
  101. IFieldFilter fieldFilter)
  102. {
  103. var typeWeaver = new ImplementFieldInterceptionHostWeaver(hostTypeFilter.ShouldWeave);
  104. var fieldWeaver = new InterceptFieldAccess(fieldFilter);
  105. var module = targetAssembly.MainModule;
  106. var targetTypes = module.Types.Where(hostTypeFilter.ShouldWeave).ToArray();
  107. foreach (var type in targetTypes)
  108. {
  109. typeWeaver.Weave(type);
  110. foreach (var method in type.Methods.Where(m => m.HasBody))
  111. {
  112. fieldWeaver.Rewrite(method, method.GetILGenerator(), method.Body.Instructions.ToArray());
  113. }
  114. }
  115. }
  116. /// <summary>
  117. /// Adds field interception support to the target type.
  118. /// </summary>
  119. /// <param name="targetAssembly">The type that will be modified.</param>
  120. /// <param name="methodFilter">
  121. /// The filter that determines which methods on the target type will be modified to support
  122. /// field interception.
  123. /// </param>
  124. /// <param name="fieldFilter">The filter that determines which fields should be intercepted.</param>
  125. public static void InterceptFields(this AssemblyDefinition targetAssembly,
  126. Func<MethodReference, bool> methodFilter,
  127. Func<FieldReference, bool> fieldFilter)
  128. {
  129. var typeWeaver = new ImplementFieldInterceptionHostWeaver(t => t.IsByReference && !t.IsValueType);
  130. var fieldWeaver = new InterceptFieldAccess(fieldFilter);
  131. var module = targetAssembly.MainModule;
  132. var targetTypes = module.Types.Where(t => t.Methods.Any(m => methodFilter(m))).ToArray();
  133. foreach (var type in targetTypes)
  134. {
  135. typeWeaver.Weave(type);
  136. foreach (var method in type.Methods.Where(m => m.HasBody))
  137. {
  138. fieldWeaver.Rewrite(method, method.GetILGenerator(), method.Body.Instructions.ToArray());
  139. }
  140. }
  141. }
  142. private static Func<MethodReference, bool> GetMethodFilter()
  143. {
  144. return m => true;
  145. }
  146. private static Func<FieldReference, bool> GetFieldFilter(Func<FieldDefinition, bool> fieldFilter)
  147. {
  148. return field =>
  149. {
  150. var actualField = field.Resolve();
  151. var fieldType = actualField.FieldType;
  152. var module = fieldType.Module;
  153. var moduleName = module != null ? module.Name : string.Empty;
  154. if (moduleName.StartsWith("LinFu.AOP"))
  155. return false;
  156. return fieldFilter(actualField);
  157. };
  158. }
  159. }
  160. }