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