ILRepack/MappingHandler.cs (113 lines of code) (raw):

using Mono.Cecil; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Fasterflect; using Mono.Cecil.Metadata; namespace ILRepacking { internal class MappingHandler { struct Pair : IEquatable<Pair> { readonly string scope; readonly string name; public readonly IMetadataScope MetadataScope; public Pair(string scope, string name, IMetadataScope metadataScope) { this.scope = scope; this.name = name; MetadataScope = metadataScope; } public override int GetHashCode() { return scope.GetHashCode() + name.GetHashCode(); } public bool Equals(Pair p) { return p.scope == scope && p.name == name; } } private readonly IDictionary<Pair, TypeDefinition> mappings = new Dictionary<Pair, TypeDefinition>(); private readonly IDictionary<Pair, TypeReference> exportMappings = new Dictionary<Pair, TypeReference>(); internal TypeDefinition GetRemappedType(TypeReference r) { TypeDefinition other; if (r.Scope != null && mappings.TryGetValue(GetTypeKey(r), out other)) { return other; } return null; } internal void StoreRemappedType(TypeDefinition orig, TypeDefinition renamed) { if (orig.Scope != null) { mappings[GetTypeKey(orig)] = renamed; } } internal void StoreExportedType(IMetadataScope scope, String fullName, TypeReference exportedTo) { if (scope != null) { exportMappings[GetTypeKey(scope, fullName)] = exportedTo; } } private static Pair GetTypeKey(TypeReference reference) { return GetTypeKey(reference.Scope, reference.FullName); } private static Pair GetTypeKey(IMetadataScope scope, String fullName) { return new Pair(GetScopeName(scope), fullName, scope); } internal static string GetScopeName(IMetadataScope scope) { if (scope is AssemblyNameReference) return ((AssemblyNameReference)scope).Name; if (scope is ModuleDefinition) return ((ModuleDefinition) scope).Assembly.Name.Name; throw new Exception("Unsupported scope: " + scope); } internal static string GetScopeFullName(IMetadataScope scope) { if (scope is AssemblyNameReference) return ((AssemblyNameReference)scope).FullName; if (scope is ModuleDefinition) return ((ModuleDefinition)scope).Assembly.Name.FullName; throw new Exception("Unsupported scope: "+ scope); } private TypeReference GetRootReference(TypeReference type) { TypeReference other; if (type.Scope != null && exportMappings.TryGetValue(GetTypeKey(type), out other)) { var next = GetRootReference(other); return next ?? other; } return null; } public TypeReference GetExportedRemappedType(TypeReference type) { TypeReference other = GetRootReference(type); if (other != null) { // ElementType is used when serializing the Assembly. // It should match the actual type (e.g., Boolean for System.Boolean). But because of forwarded types, this is not known at read time, thus having to fix it here. var etype = type.GetFieldValue("etype"); if (etype != (object) 0x0) { other.SetFieldValue("etype", etype); } // when reading forwarded types, we don't know if they are value types, fix that later on if (type.IsValueType && !other.IsValueType) other.IsValueType = true; return other; } return null; } internal T GetOrigTypeScope<T>(TypeDefinition nt) where T : class, IMetadataScope { return mappings.Where(p => p.Value == nt).Select(p => p.Key.MetadataScope).FirstOrDefault() as T; } } }