in src/Adapter/PlatformServices.Desktop.Legacy/AssemblyResolver.cs [394:536]
private Assembly OnResolveInternal(object senderAppDomain, ResolveEventArgs args, bool isReflectionOnly)
{
if (string.IsNullOrEmpty(args?.Name))
{
Debug.Fail("AssemblyResolver.OnResolve: args.Name is null or empty.");
return null;
}
this.SafeLog(
args.Name,
() =>
{
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("AssemblyResolver: Resolving assembly: {0}.", args.Name);
}
});
string assemblyNameToLoad = AppDomain.CurrentDomain.ApplyPolicy(args.Name);
this.SafeLog(
assemblyNameToLoad,
() =>
{
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("AssemblyResolver: Resolving assembly after applying policy: {0}.", assemblyNameToLoad);
}
});
lock (this.syncLock)
{
// Since both normal and reflection only cache are accessed in same block, putting only one lock should be sufficient.
if (this.TryLoadFromCache(assemblyNameToLoad, isReflectionOnly, out var assembly))
{
return assembly;
}
assembly = this.SearchAssembly(this.searchDirectories, assemblyNameToLoad, isReflectionOnly);
if (assembly != null)
{
return assembly;
}
if (this.directoryList != null && this.directoryList.Any())
{
// required assembly is not present in searchDirectories??
// see, if we can find it in user specified search directories.
while (assembly == null && this.directoryList.Count > 0)
{
// instead of loading whole search directory in one time, we are adding directory on the basis of need
var currentNode = this.directoryList.Dequeue();
List<string> increamentalSearchDirectory = new List<string>();
if (this.DoesDirectoryExist(currentNode.DirectoryPath))
{
increamentalSearchDirectory.Add(currentNode.DirectoryPath);
if (currentNode.IncludeSubDirectories)
{
// Add all its sub-directory in depth first search order.
this.AddSubdirectories(currentNode.DirectoryPath, increamentalSearchDirectory);
}
// Add this directory list in this.searchDirectories so that when we will try to resolve some other
// assembly, then it will look in this whole directory first.
this.searchDirectories.AddRange(increamentalSearchDirectory);
assembly = this.SearchAssembly(increamentalSearchDirectory, assemblyNameToLoad, isReflectionOnly);
}
else
{
// generate warning that path does not exist.
this.SafeLog(
assemblyNameToLoad,
() =>
{
if (EqtTrace.IsWarningEnabled)
{
EqtTrace.Warning(
"The Directory: {0}, does not exist",
currentNode.DirectoryPath);
}
});
}
}
if (assembly != null)
{
return assembly;
}
}
// Try for default load for System dlls that can't be found in search paths. Needs to loaded just by name.
try
{
if (isReflectionOnly)
{
// Put it in the resolved assembly cache so that if the Load call below
// triggers another assembly resolution, then we don't end up in stack overflow.
this.reflectionOnlyResolvedAssemblies[assemblyNameToLoad] = null;
assembly = Assembly.ReflectionOnlyLoad(assemblyNameToLoad);
if (assembly != null)
{
this.reflectionOnlyResolvedAssemblies[assemblyNameToLoad] = assembly;
}
}
else
{
// Put it in the resolved assembly cache so that if the Load call below
// triggers another assembly resolution, then we don't end up in stack overflow.
this.resolvedAssemblies[assemblyNameToLoad] = null;
assembly = Assembly.Load(assemblyNameToLoad);
if (assembly != null)
{
this.resolvedAssemblies[assemblyNameToLoad] = assembly;
}
}
return assembly;
}
catch (Exception ex)
{
this.SafeLog(
args?.Name,
() =>
{
if (EqtTrace.IsInfoEnabled)
{
EqtTrace.Info("AssemblyResolver: {0}: Failed to load assembly. Reason: {1}", assemblyNameToLoad, ex);
}
});
}
return assembly;
}
}