/src/LinFu.AOP/Emitters/EmitAfterInvoke.cs

http://github.com/philiplaureano/LinFu · C# · 80 lines · 49 code · 12 blank · 19 comment · 0 complexity · 38575902b3f828019e5b47cf3e81120d MD5 · raw file

  1. using LinFu.AOP.Cecil.Interfaces;
  2. using LinFu.AOP.Interfaces;
  3. using LinFu.Reflection.Emit;
  4. using Mono.Cecil;
  5. using Mono.Cecil.Cil;
  6. namespace LinFu.AOP.Cecil
  7. {
  8. /// <summary>
  9. /// Represents a type that emits the call to the <see cref="IAfterInvoke" /> instance.
  10. /// </summary>
  11. public class EmitAfterInvoke : IInstructionEmitter
  12. {
  13. private readonly VariableDefinition _invocationInfo;
  14. private readonly VariableDefinition _returnValue;
  15. private readonly VariableDefinition _surroundingClassImplementation;
  16. private readonly VariableDefinition _surroundingImplementation;
  17. /// <summary>
  18. /// Initializes a new instance of the <see cref="EmitAfterInvoke" /> class.
  19. /// </summary>
  20. /// <param name="surroundingImplementation">The variable that contains the <see cref="IAroundInvoke" /> instance.</param>
  21. /// <param name="surroundingClassImplementation">
  22. /// The variable that contains the class-level <see cref="IAroundInvoke" />
  23. /// instance.
  24. /// </param>
  25. /// <param name="invocationInfo">The variable that contains the <see cref="IInvocationInfo" /> instance.</param>
  26. /// <param name="returnValue">The local vaiable that contains the return value of the target method.</param>
  27. public EmitAfterInvoke(VariableDefinition surroundingImplementation,
  28. VariableDefinition surroundingClassImplementation,
  29. VariableDefinition invocationInfo, VariableDefinition returnValue)
  30. {
  31. _surroundingImplementation = surroundingImplementation;
  32. _surroundingClassImplementation = surroundingClassImplementation;
  33. _invocationInfo = invocationInfo;
  34. _returnValue = returnValue;
  35. }
  36. /// <summary>
  37. /// Emits the call to the <see cref="IAfterInvoke" /> instance.
  38. /// </summary>
  39. /// <param name="IL">The <see cref="ILProcessor" /> that points to the current method body.</param>
  40. public void Emit(ILProcessor IL)
  41. {
  42. var module = IL.Body.Method.DeclaringType.Module;
  43. // instanceAroundInvoke.AfterInvoke(info, returnValue);
  44. Emit(IL, module, _surroundingImplementation, _invocationInfo, _returnValue);
  45. // classAroundInvoke.AfterInvoke(info, returnValue);
  46. Emit(IL, module, _surroundingClassImplementation, _invocationInfo, _returnValue);
  47. }
  48. private static void Emit(ILProcessor IL, ModuleDefinition module,
  49. VariableDefinition surroundingImplementation,
  50. VariableDefinition invocationInfo,
  51. VariableDefinition returnValue)
  52. {
  53. var skipInvoke = IL.Create(OpCodes.Nop);
  54. var skipPrint = IL.Create(OpCodes.Nop);
  55. IL.Emit(OpCodes.Ldloc, surroundingImplementation);
  56. IL.Emit(OpCodes.Brtrue, skipPrint);
  57. IL.Append(skipPrint);
  58. IL.Emit(OpCodes.Ldloc, surroundingImplementation);
  59. IL.Emit(OpCodes.Brfalse, skipInvoke);
  60. var aroundInvoke = module.ImportMethod<IAfterInvoke>("AfterInvoke");
  61. IL.Emit(OpCodes.Ldloc, surroundingImplementation);
  62. IL.Emit(OpCodes.Ldloc, invocationInfo);
  63. IL.Emit(OpCodes.Ldloc, returnValue);
  64. IL.Emit(OpCodes.Callvirt, aroundInvoke);
  65. IL.Append(skipInvoke);
  66. }
  67. }
  68. }