Using VS2017 RC, .NET Core
I am trying to load an assembly from a file. The dependencies of this assembly are in the same folder.
I am using AssemblyLoadContext.Default.LoadFromAssemblyPath
.
I realize LoadFromAssemblyPath
exclusively loads the requested assembly, ignoring its dependencies; any attempt to iterate through the assembly types fails with a System.Reflection.ReflectionTypeLoadException
.
LoaderExceptions
contains a list of System.IO.FileNotFoundException
.
I'm curious as to why this is the case, since all the required files are in the same folder.
I also tried to load all *.dll files in a folder, but some surprisingly fail with a System.IO.FileLoadException
.
What am I doing wrong?
Edit: I wouldn't want to rely on the .deps file (thus ruling out DependencyContext). Is it possible?
Loads an assembly with the specified name. Loads an assembly given its AssemblyName. Loads the assembly with a common object file format (COFF)-based image containing an emitted assembly, optionally including symbols for the assembly. The assembly is loaded into the application domain of the caller.
An assembly is a collection of types and resources that are built to work together and form a logical unit of functionality. Assemblies take the form of executable (.exe) or dynamic link library (. dll) files, and are the building blocks of . NET applications.
After the correct assembly version has been determined by using the information in the calling assembly's reference and in the configuration files, and after it has checked in the global assembly cache (only for strong-named assemblies), the common language runtime attempts to find the assembly.
LoadFrom(String) Loads an assembly given its file name or path.
Well what works for me is to register a handle with the Resolving event and load required assemblies on demand when LoadFromAssemblyPath needs dependencies. Be aware that this my solution from hours of trial and error, so it might not be the most ideal way. It works for me by now though. Here's my code:
AssemblyLoadContext.Default.Resolving += (context, name) =>
{
// avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416
if (name.Name.EndsWith("resources"))
{
return null;
}
var dependencies = DependencyContext.Default.RuntimeLibraries;
foreach (var library in dependencies)
{
if (IsCandidateLibrary(library, name))
{
return context.LoadFromAssemblyName(new AssemblyName(library.Name));
}
}
var foundDlls = Directory.GetFileSystemEntries(new FileInfo(<YOUR_PATH_HERE>).FullName, name.Name + ".dll", SearchOption.AllDirectories);
if (foundDlls.Any())
{
return context.LoadFromAssemblyPath(foundDlls[0]);
}
return context.LoadFromAssemblyName(name);
};
}
private static bool IsCandidateLibrary(RuntimeLibrary library, AssemblyName assemblyName)
{
return (library.Name == (assemblyName.Name))
|| (library.Dependencies.Any(d => d.Name.StartsWith(assemblyName.Name)));
}
The IsCandidateLibrary() bit originates from there: http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/
I think you could omit this and the whole DependencyContext part, but it acts as a cache and avoids reloading the same assemblies over and over again. So i kept it.
There is a great enhancement in .Net Core 3.0+, wire AssemblyLoadContext.Default.Resolving
event as given below and all dependencies will be resolved and loaded:
AssemblyLoadContext.Default.Resolving += (context, name) => {
string assemblyPath = $"{pluginFolder}\\{name.Name}.dll";
if (assemblyPath != null)
return context.LoadFromAssemblyPath(assemblyPath);
return null;
};
Remember to define the variabe pluginFolder
Solution2
You can use the AssemblyDependencyResolver
class and resolve dependendencies including ones in .deps.json
:
var resolver = new AssemblyDependencyResolver(pluginPath);
AssemblyLoadContext.Default.Resolving += (context, name) => {
string assemblyPath = resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
return context.LoadFromAssemblyPath(assemblyPath);
return null;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With