/src/LinFu.AOP/BaseMethodRewriter.cs

http://github.com/philiplaureano/LinFu · C# · 96 lines · 45 code · 18 blank · 33 comment · 4 complexity · 452f1c1f4e871addc6466fbad13317b4 MD5 · raw file

  1. using System.Collections.Generic;
  2. using LinFu.AOP.Cecil.Interfaces;
  3. using Mono.Cecil;
  4. using Mono.Cecil.Cil;
  5. namespace LinFu.AOP.Cecil
  6. {
  7. /// <summary>
  8. /// Represents the basic implementation of a method rewriter class.
  9. /// </summary>
  10. public abstract class BaseMethodRewriter : IMethodRewriter
  11. {
  12. private readonly HashSet<TypeDefinition> _modifiedTypes = new HashSet<TypeDefinition>();
  13. /// <summary>
  14. /// Rewrites a target method using the given ILProcessor.
  15. /// </summary>
  16. /// <param name="method">The target method.</param>
  17. /// <param name="IL">The ILProcessor that will be used to rewrite the target method.</param>
  18. /// <param name="oldInstructions">The original instructions from the target method body.</param>
  19. public void Rewrite(MethodDefinition method, ILProcessor IL, IEnumerable<Instruction> oldInstructions)
  20. {
  21. if (!ShouldRewrite(method))
  22. return;
  23. var declaringType = method.DeclaringType;
  24. var body = IL.Body;
  25. body.InitLocals = true;
  26. var module = declaringType.Module;
  27. // Interfaces and Enums cannot be modified
  28. if (declaringType.IsInterface || declaringType.IsEnum)
  29. return;
  30. ImportReferences(module);
  31. AddLocals(method);
  32. if (!_modifiedTypes.Contains(declaringType))
  33. {
  34. AddAdditionalMembers(declaringType);
  35. _modifiedTypes.Add(declaringType);
  36. }
  37. RewriteMethodBody(method, IL, oldInstructions);
  38. }
  39. /// <summary>
  40. /// Adds additional members to the host type.
  41. /// </summary>
  42. /// <param name="host">The host type.</param>
  43. public virtual void AddAdditionalMembers(TypeDefinition host)
  44. {
  45. }
  46. /// <summary>
  47. /// Adds additional references to the target module.
  48. /// </summary>
  49. /// <param name="module">The host module.</param>
  50. public virtual void ImportReferences(ModuleDefinition module)
  51. {
  52. }
  53. /// <summary>
  54. /// Adds local variables to the <paramref name="hostMethod" />.
  55. /// </summary>
  56. /// <param name="hostMethod">The target method.</param>
  57. public virtual void AddLocals(MethodDefinition hostMethod)
  58. {
  59. }
  60. /// <summary>
  61. /// Determines whether or not the given method should be modified.
  62. /// </summary>
  63. /// <param name="targetMethod">The target method.</param>
  64. /// <returns>A <see cref="bool" /> indicating whether or not a method should be rewritten.</returns>
  65. protected virtual bool ShouldRewrite(MethodDefinition targetMethod)
  66. {
  67. return true;
  68. }
  69. /// <summary>
  70. /// Rewrites the instructions in the target method body.
  71. /// </summary>
  72. /// <param name="method">The target method.</param>
  73. /// <param name="IL">The <see cref="ILProcessor" /> instance that represents the method body.</param>
  74. /// <param name="oldInstructions">The IL instructions of the original method body.</param>
  75. protected abstract void RewriteMethodBody(MethodDefinition method, ILProcessor IL,
  76. IEnumerable<Instruction> oldInstructions);
  77. }
  78. }