mirror of https://github.com/icsharpcode/ILSpy.git
10 changed files with 384 additions and 301 deletions
@ -0,0 +1,147 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using System.Windows.Threading; |
||||||
|
|
||||||
|
using Mono.Cecil; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Represents an assembly loaded into ILSpy.
|
||||||
|
/// </summary>
|
||||||
|
sealed class LoadedAssembly |
||||||
|
{ |
||||||
|
readonly Task<AssemblyDefinition> assemblyTask; |
||||||
|
readonly AssemblyList assemblyList; |
||||||
|
readonly string fileName; |
||||||
|
string shortName; |
||||||
|
|
||||||
|
public LoadedAssembly(AssemblyList assemblyList, string fileName) |
||||||
|
{ |
||||||
|
if (assemblyList == null) |
||||||
|
throw new ArgumentNullException("assemblyList"); |
||||||
|
if (fileName == null) |
||||||
|
throw new ArgumentNullException("fileName"); |
||||||
|
this.assemblyList = assemblyList; |
||||||
|
this.fileName = fileName; |
||||||
|
|
||||||
|
this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
|
||||||
|
this.shortName = Path.GetFileNameWithoutExtension(fileName); |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyDefinition AssemblyDefinition { |
||||||
|
get { |
||||||
|
try { |
||||||
|
return assemblyTask.Result; |
||||||
|
} catch (AggregateException) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyList AssemblyList { |
||||||
|
get { return assemblyList; } |
||||||
|
} |
||||||
|
|
||||||
|
public string FileName { |
||||||
|
get { return fileName; } |
||||||
|
} |
||||||
|
|
||||||
|
public string ShortName { |
||||||
|
get { return shortName; } |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsLoaded { |
||||||
|
get { return assemblyTask.IsCompleted; } |
||||||
|
} |
||||||
|
|
||||||
|
public bool HasLoadError { |
||||||
|
get { return assemblyTask.IsFaulted; } |
||||||
|
} |
||||||
|
|
||||||
|
AssemblyDefinition LoadAssembly() |
||||||
|
{ |
||||||
|
// runs on background thread
|
||||||
|
ReaderParameters p = new ReaderParameters(); |
||||||
|
p.AssemblyResolver = new MyAssemblyResolver(this); |
||||||
|
return AssemblyDefinition.ReadAssembly(fileName, p); |
||||||
|
} |
||||||
|
|
||||||
|
sealed class MyAssemblyResolver : IAssemblyResolver |
||||||
|
{ |
||||||
|
readonly LoadedAssembly parent; |
||||||
|
|
||||||
|
public MyAssemblyResolver(LoadedAssembly parent) |
||||||
|
{ |
||||||
|
this.parent = parent; |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(AssemblyNameReference name) |
||||||
|
{ |
||||||
|
var node = parent.LookupReferencedAssembly(name.FullName); |
||||||
|
return node != null ? node.AssemblyDefinition : null; |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) |
||||||
|
{ |
||||||
|
var node = parent.LookupReferencedAssembly(name.FullName); |
||||||
|
return node != null ? node.AssemblyDefinition : null; |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(string fullName) |
||||||
|
{ |
||||||
|
var node = parent.LookupReferencedAssembly(fullName); |
||||||
|
return node != null ? node.AssemblyDefinition : null; |
||||||
|
} |
||||||
|
|
||||||
|
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters) |
||||||
|
{ |
||||||
|
var node = parent.LookupReferencedAssembly(fullName); |
||||||
|
return node != null ? node.AssemblyDefinition : null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public LoadedAssembly LookupReferencedAssembly(string fullName) |
||||||
|
{ |
||||||
|
foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) { |
||||||
|
if (asm.AssemblyDefinition != null && fullName.Equals(asm.AssemblyDefinition.FullName, StringComparison.OrdinalIgnoreCase)) |
||||||
|
return asm; |
||||||
|
} |
||||||
|
|
||||||
|
if (!App.Current.Dispatcher.CheckAccess()) { |
||||||
|
// Call this method on the GUI thread.
|
||||||
|
return (LoadedAssembly)App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Func<string, LoadedAssembly>(LookupReferencedAssembly), fullName); |
||||||
|
} |
||||||
|
|
||||||
|
var name = AssemblyNameReference.Parse(fullName); |
||||||
|
string file = GacInterop.FindAssemblyInNetGac(name); |
||||||
|
if (file == null) { |
||||||
|
string dir = Path.GetDirectoryName(this.fileName); |
||||||
|
if (File.Exists(Path.Combine(dir, name.Name + ".dll"))) |
||||||
|
file = Path.Combine(dir, name.Name + ".dll"); |
||||||
|
else if (File.Exists(Path.Combine(dir, name.Name + ".exe"))) |
||||||
|
file = Path.Combine(dir, name.Name + ".exe"); |
||||||
|
} |
||||||
|
if (file != null) { |
||||||
|
return assemblyList.OpenAssembly(file); |
||||||
|
} else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Task ContinueWhenLoaded(Action<Task<AssemblyDefinition>> onAssemblyLoaded, TaskScheduler taskScheduler) |
||||||
|
{ |
||||||
|
return this.assemblyTask.ContinueWith(onAssemblyLoaded, taskScheduler); |
||||||
|
} |
||||||
|
|
||||||
|
public void WaitUntilLoaded() |
||||||
|
{ |
||||||
|
assemblyTask.Wait(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue