使用VS2017 RC,.NET Core
我正在尝试从文件加载程序集。 此程序集的依赖项位于同一文件夹中。
我正在使用LoadFromAssemblyPath
。
我意识到System.Reflection.ReflectionTypeLoadException
只是加载所请求的程序集,忽略它的依赖关系;任何迭代装配类型的尝试都失败了LoaderExceptions
。
System.IO.FileNotFoundException
包含System.IO.FileLoadException
的列表。
我很好奇为什么会这样,因为所有必需的文件都在同一个文件夹中。
我还尝试将所有* .dll文件加载到一个文件夹中,但有些令人惊讶地失败了"react-router": "^3.0.0"
。
我做错了什么?
编辑:我不想依赖.deps文件(因此排除了DependencyContext)。有可能吗?
答案 0 :(得分:8)
对我来说有用的是在LoadFromAssemblyPath需要依赖项时,使用Resolving事件注册句柄并按需加载所需的程序集。请注意这是我的解决方案,从几个小时的试验和错误,所以它可能不是最理想的方式。它现在适用于我。这是我的代码:
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)));
}
IsCandidateLibrary()位来源于: http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/
我认为你可以省略这个和整个DependencyContext部分,但它充当缓存并避免一遍又一遍地重新加载相同的程序集。所以我保留了它。
答案 1 :(得分:3)
.Net Core 3.0+中有一个很大的增强,如下所示,发生了AssemblyLoadContext.Default.Resolving
事件,所有依赖关系都将被解析和加载:
AssemblyLoadContext.Default.Resolving += (context, name) => {
string assemblyPath = $"{pluginFolder}\\{name.Name}.dll";
if (assemblyPath != null)
return context.LoadFromAssemblyPath(assemblyPath);
return null;
};
记住要定义变量pluginFolder
解决方案2
您可以使用AssemblyDependencyResolver
类并解决依赖关系,包括.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;
};