提交 57c05a8f 编写于 作者: T Tomas Matousek

Use custom resolver only when default resolver fails to load an assembly

上级 ffe0709d
......@@ -15,7 +15,7 @@ internal sealed class CoreAssemblyLoaderImpl : AssemblyLoaderImpl
internal CoreAssemblyLoaderImpl(InteractiveAssemblyLoader loader)
: base(loader)
{
_inMemoryAssemblyContext = new LoadContext(this, null);
_inMemoryAssemblyContext = new LoadContext(Loader, null);
}
public override Assembly LoadFromStream(Stream peStream, Stream pdbStream)
......@@ -25,7 +25,11 @@ public override Assembly LoadFromStream(Stream peStream, Stream pdbStream)
public override AssemblyAndLocation LoadFromPath(string path)
{
var assembly = new LoadContext(this, Path.GetDirectoryName(path)).LoadFromAssemblyPath(path);
// Create a new context that knows the directory where the assembly was loaded from
// and uses it to resolve dependencies of the assembly. We could create one context per directory,
// but there is no need to reuse contexts.
var assembly = new LoadContext(Loader, Path.GetDirectoryName(path)).LoadFromAssemblyPath(path);
return new AssemblyAndLocation(assembly, path, fromGac: false);
}
......@@ -37,30 +41,33 @@ public override void Dispose()
private sealed class LoadContext : AssemblyLoadContext
{
private readonly string _loadDirectoryOpt;
private readonly CoreAssemblyLoaderImpl _loader;
private readonly InteractiveAssemblyLoader _loader;
internal LoadContext(CoreAssemblyLoaderImpl loader, string loadDirectoryOpt)
internal LoadContext(InteractiveAssemblyLoader loader, string loadDirectoryOpt)
{
Debug.Assert(loader != null);
_loader = loader;
_loadDirectoryOpt = loadDirectoryOpt;
}
protected override Assembly Load(AssemblyName assemblyName)
{
return _loader.Loader.ResolveAssembly(AssemblyIdentity.FromAssemblyReference(assemblyName), _loadDirectoryOpt) ??
Default.LoadFromAssemblyName(assemblyName);
}
// CoreCLR resolves assemblies in steps:
//
// 1) Call AssemblyLoadContext.Load -- our context returns null
// 2) TPA list
// 3) Default.Resolving event
// 4) AssemblyLoadContext.Resolving event -- hooked below
//
// What we want is to let the default context load assemblies it knows about (this includes already loaded assemblies,
// assemblies in AppPath, platform assemblies, assemblies explciitly resolved by the App by hooking Default.Resolving, etc.).
// Only if the assembly can't be resolved that way, the interactive resolver steps in.
//
// This order is necessary to avoid loading assemblies twice (by the host App and by interactive loader).
public new Assembly LoadFromStream(Stream assembly, Stream assemblySymbols)
{
return base.LoadFromStream(assembly, assemblySymbols);
Resolving += (_, assemblyName) =>
_loader.ResolveAssembly(AssemblyIdentity.FromAssemblyReference(assemblyName), _loadDirectoryOpt);
}
public new Assembly LoadFromAssemblyPath(string assemblyPath)
{
return base.LoadFromAssemblyPath(assemblyPath);
}
protected override Assembly Load(AssemblyName assemblyName) => null;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册