PageRenderTime 52ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 0ms

/src/LinFu.AOP/Loaders/JITWeaver.cs

http://github.com/philiplaureano/LinFu
C# | 102 lines | 52 code | 20 blank | 30 comment | 12 complexity | 01f6abf8f700c156764a22d97f928af6 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using LinFu.AOP.Cecil.Interfaces;
  6. using LinFu.Reflection;
  7. using LinFu.Reflection.Emit;
  8. using Mono.Cecil;
  9. namespace LinFu.AOP.Cecil.Loaders
  10. {
  11. /// <summary>
  12. /// Represents a loader that modifies a given assembly prior to being loaded from disk.
  13. /// </summary>
  14. public class JITWeaver : AssemblyLoader
  15. {
  16. private readonly List<Action<AssemblyDefinition>> _assemblyWeavers = new List<Action<AssemblyDefinition>>();
  17. /// <summary>
  18. /// Initializes a new instance of the <see cref="JITWeaver" /> class.
  19. /// </summary>
  20. public JITWeaver()
  21. : this(new PdbLoader())
  22. {
  23. }
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="JITWeaver" /> class.
  26. /// </summary>
  27. /// <param name="pdbLoader">The loader that will be responsible for loading the program debugging information into memory.</param>
  28. public JITWeaver(IPdbLoader pdbLoader)
  29. {
  30. PdbLoader = pdbLoader;
  31. }
  32. /// <summary>
  33. /// Gets or sets the value indicating the <see cref="IPdbLoader" /> that will be used to load debug symbols into
  34. /// memory.
  35. /// </summary>
  36. public IPdbLoader PdbLoader { get; set; }
  37. /// <summary>
  38. /// Gets the value indicating the list of <see cref="Action{T}" /> delegates
  39. /// that will be used to modify the assemblies loaded into memory.
  40. /// </summary>
  41. public virtual IList<Action<AssemblyDefinition>> AssemblyWeavers => _assemblyWeavers;
  42. /// <summary>
  43. /// Gets or sets the value indicating the <see cref="IVerifier" />
  44. /// instance that will be used to ensure that the modified assemblies are valid.
  45. /// </summary>
  46. public virtual IVerifier AssemblyVerifier { get; set; }
  47. /// <summary>
  48. /// Modifies a given assembly prior to being loaded from disk.
  49. /// </summary>
  50. /// <param name="assemblyFile">The filename of the target assembly.</param>
  51. /// <returns>A valid assembly.</returns>
  52. public override Assembly Load(string assemblyFile)
  53. {
  54. var targetAssembly = AssemblyDefinition.ReadAssembly(assemblyFile);
  55. // Strongly-named assemblies cannot be modified
  56. if (targetAssembly.Name.HasPublicKey)
  57. return base.Load(assemblyFile);
  58. var assemblyFileName = Path.GetFileNameWithoutExtension(assemblyFile);
  59. var pdbFile = string.Format("{0}.pdb", assemblyFileName);
  60. var hasSymbols = File.Exists(pdbFile);
  61. if (PdbLoader != null && hasSymbols)
  62. PdbLoader.LoadSymbols(targetAssembly);
  63. foreach (var action in AssemblyWeavers)
  64. {
  65. action(targetAssembly);
  66. // Verify the assembly at every step
  67. if (AssemblyVerifier == null)
  68. continue;
  69. AssemblyVerifier.Verify(targetAssembly);
  70. }
  71. var memoryStream = new MemoryStream();
  72. if (PdbLoader != null && hasSymbols)
  73. PdbLoader.SaveSymbols(targetAssembly);
  74. // Save the modifed assembly
  75. targetAssembly.Save(memoryStream);
  76. if (PdbLoader == null || !hasSymbols)
  77. return targetAssembly.ToAssembly();
  78. var pdbBytes = File.ReadAllBytes(pdbFile);
  79. return PdbLoader.LoadAssembly(memoryStream.ToArray(), pdbBytes);
  80. }
  81. }
  82. }