Browse Source

Add IAssemblyResolver.ResolveModule

pull/1030/head
Siegfried Pammer 7 years ago
parent
commit
ab977c95a6
  1. 1
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  2. 12
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  3. 35
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

1
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -47,6 +47,7 @@ namespace ICSharpCode.Decompiler.Metadata
public interface IAssemblyResolver
{
PEFile Resolve(IAssemblyReference reference);
PEFile ResolveModule(PEFile mainModule, string moduleName);
}
public interface IAssemblyReference

12
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -93,6 +93,18 @@ namespace ICSharpCode.Decompiler.Metadata @@ -93,6 +93,18 @@ namespace ICSharpCode.Decompiler.Metadata
return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), options);
}
public PEFile ResolveModule(PEFile mainModule, string moduleName)
{
string baseDirectory = Path.GetDirectoryName(mainModule.FileName);
string moduleFileName = Path.Combine(baseDirectory, moduleName);
if (!File.Exists(moduleFileName)) {
if (throwOnError)
throw new Exception($"Module {moduleName} could not be found!");
return null;
}
return new PEFile(moduleFileName, new FileStream(moduleFileName, FileMode.Open, FileAccess.Read), options);
}
public string FindAssemblyFile(IAssemblyReference name)
{
var targetFramework = TargetFramework.Split(new[] { ",Version=v" }, StringSplitOptions.None);

35
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -104,20 +104,43 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -104,20 +104,43 @@ namespace ICSharpCode.Decompiler.TypeSystem
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<IAssemblyReference>();
var assemblyReferenceQueue = new Queue<Metadata.AssemblyReference>(moduleDefinition.AssemblyReferences);
var processedAssemblyReferences = new HashSet<Metadata.AssemblyReference>(KeyComparer.Create((Metadata.AssemblyReference reference) => reference.FullName));
var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>();
var mainMetadata = moduleDefinition.Metadata;
foreach (var h in mainMetadata.GetModuleReferences()) {
var moduleRef = mainMetadata.GetModuleReference(h);
assemblyReferenceQueue.Enqueue((false, moduleDefinition, mainMetadata.GetString(moduleRef.Name)));
}
foreach (var refs in moduleDefinition.AssemblyReferences) {
assemblyReferenceQueue.Enqueue((true, moduleDefinition, refs));
}
var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) =>
reference.IsAssembly ? "A:" + reference.MainModule.FileName + ":" + ((AssemblyReference)reference.Reference).FullName :
"M:" + reference.MainModule.FileName + ":" + reference.Reference);
var processedAssemblyReferences = new HashSet<(bool IsAssembly, PEFile Parent, object Reference)>(comparer);
while (assemblyReferenceQueue.Count > 0) {
var asmRef = assemblyReferenceQueue.Dequeue();
if (!processedAssemblyReferences.Add(asmRef))
continue;
var asm = assemblyResolver.Resolve(asmRef);
PEFile asm;
if (asmRef.IsAssembly) {
asm = assemblyResolver.Resolve((AssemblyReference)asmRef.Reference);
} else {
asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference);
}
if (asm != null) {
referencedAssemblies.Add(asm.WithOptions(typeSystemOptions));
var metadata = asm.Metadata;
foreach (var h in metadata.ExportedTypes) {
var forwarder = metadata.GetExportedType(h);
if (!forwarder.IsForwarder || forwarder.Implementation.Kind != SRM.HandleKind.AssemblyReference) continue;
assemblyReferenceQueue.Enqueue(new Metadata.AssemblyReference(asm, (SRM.AssemblyReferenceHandle)forwarder.Implementation));
var exportedType = metadata.GetExportedType(h);
switch (exportedType.Implementation.Kind) {
case SRM.HandleKind.AssemblyReference:
assemblyReferenceQueue.Enqueue((true, asm, new AssemblyReference(asm, (SRM.AssemblyReferenceHandle)exportedType.Implementation)));
break;
case SRM.HandleKind.AssemblyFile:
var file = metadata.GetAssemblyFile((SRM.AssemblyFileHandle)exportedType.Implementation);
assemblyReferenceQueue.Enqueue((false, asm, metadata.GetString(file.Name)));
break;
}
}
}
}

Loading…
Cancel
Save