我目前正在使用1
,并对如何处理库可能具有的任何nuget依赖项感到好奇?
例如: 库A动态加载库B. 图书馆B依赖于NuGet的Redis。
库B正确加载,但在使用redis客户端时 - 我们得到一个令人讨厌的FileNotFoundException抱怨无法找到redis程序集。该场景实际上是典型的模块加载器类型。
AssemblyLoadContext.Default.LoadFromAssemblyPath(path/to/netstandard1.6lib.dll)
当Activator创建实例时,扩展程序的构造函数会尝试创建一个新的redis客户端 - 而这一切都会爆炸。
关于如何在运行时从nuget处理第三级依赖关系的任何想法?
答案 0 :(得分:1)
DLL必须在那里加载它们,AFAIK你不应该在运行时下载nugget包,因为它会很慢,并且它可以在块金来源不可用的任何时候停止工作,或者更可能,你没有互联网连接。
因此,让您的项目依赖于该块包,并在构建之前下载它。
如果你对这种方法不感兴趣,那么我想你可以尝试从你的程序中执行NuGet.exe并让它首先下载所需的DLL,但这会让你的程序在下载程序包时挂断文件。
答案 1 :(得分:0)
我最终需要做的是在项目的csproj文件中添加:<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
然后调整我的模块加载器代码以迭代所有DLL并加载它们,然后尝试通过激活器从我的程序集中调用构造函数。
public void LoadExtensions()
{
IConfigurationSection[] extensionConfigurations = _config.GetSections(EXTENSION_CONFIGURATION_KEY).ToArray();
if (extensionConfigurations.Length == 0)
return;
HashSet<IExtension> extensions = new HashSet<IExtension>();
foreach (IConfigurationSection extensionConfiguration in extensionConfigurations)
{
string name = extensionConfiguration.Key;
string path = _config.Get($"{extensionConfiguration.Path}:path");
_logger.Debug($"Loading extension: {name}");
if (string.IsNullOrEmpty(path) || !File.Exists(path))
throw new ConfigurationItemMissingException($"{extensionConfiguration.Path}:path");
LoadAssembly(path, name);
}
foreach (var extensionType in _extensionTypes)
{
IExtension extension = Activator.CreateInstance(extensionType.Key.AsType(), extensionType.Value, _dependencyUtility) as IExtension;
if (extension == null)
throw new InvalidExtensionException(extensionType.Value, extensionType.Key.AssemblyQualifiedName);
extensions.Add(extension);
}
Extensions = extensions;
}
private void LoadAssembly(string path, string name)
{
FileInfo[] dlls = new DirectoryInfo(Path.GetDirectoryName(path)).GetFiles("*.dll");
foreach (FileInfo dll in dlls)
{
Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(dll.FullName);
_logger.Info($"Loading assembly: {asm.FullName}");
TypeInfo type = asm.DefinedTypes.FirstOrDefault(x => x.ImplementedInterfaces.Contains(typeof(IExtension)) && !x.IsAbstract);
if (type == null)
continue;
_extensionTypes.Add(type, name);
}
}
答案 2 :(得分:-1)
您不应手动解决程序集依赖关系。
只需确保在动态加载 Library B 时,.net运行时即可访问所有相关的dll-s。默认情况下,它会检查您的应用进程和GAC的工作目录。
如果要自定义运行时的探测行为,可以使用配置文件中的<probing>
设置或C#代码中的设置来执行此操作。
我建议你阅读这些文档,它们应该帮助你理解探究如何更详细地运作:
https://docs.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/specify-assembly-location
要对依赖项解决方案进行问题排查,您可以使用 fuslog 工具:
https://docs.microsoft.com/en-us/dotnet/framework/tools/fuslogvw-exe-assembly-binding-log-viewer