.NET Core无法从基础目录加载程序集的技术问题咨询
我之前也碰到过这个类似的问题,.NET Core的程序集加载策略和.NET Framework确实有很大差异——Framework会自动在应用基础目录里扫描匹配的程序集,但.NET Core默认不会这么做,它的加载逻辑更偏向依赖项的显式管理(比如通过NuGet或者runtimeconfig配置),所以直接用程序集全名调用Assembly.Load()就会抛出FileNotFoundException。
下面给你几个可行的解决方案:
方案1:使用AssemblyLoadContext直接加载指定路径的程序集
这是最可靠的方式,你可以先获取应用的基础目录,拼接出目标dll的完整路径,然后通过AssemblyLoadContext来加载:
using System.Reflection; using System.Runtime.Loader; using System.IO; // 获取应用基础目录 var baseDirectory = AppContext.BaseDirectory; // 拼接dll的完整路径 var dllPath = Path.Combine(baseDirectory, "HsopPaas.dll"); // 加载程序集 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(dllPath);
这种方式直接指定了程序集的物理路径,绕开了.NET Core的默认依赖扫描逻辑,几乎不会出问题。
方案2:自定义AssemblyLoadContext实现目录扫描
如果你的场景需要动态加载多个目录下的程序集,可以自定义一个AssemblyLoadContext,重写它的Load方法,让它去指定目录查找匹配的程序集:
using System.Reflection; using System.Runtime.Loader; using System.IO; public class CustomAssemblyLoadContext : AssemblyLoadContext { private readonly string _assemblyDirectory; public CustomAssemblyLoadContext(string assemblyDirectory) { _assemblyDirectory = assemblyDirectory; } protected override Assembly? Load(AssemblyName assemblyName) { var assemblyPath = Path.Combine(_assemblyDirectory, $"{assemblyName.Name}.dll"); if (File.Exists(assemblyPath)) { return LoadFromAssemblyPath(assemblyPath); } // 如果当前目录找不到,回退到默认加载逻辑 return null; } } // 使用示例 var alc = new CustomAssemblyLoadContext(AppContext.BaseDirectory); var assembly = alc.Load(new AssemblyName("HsopPaas, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
方案3:配置runtimeconfig.json添加探测路径
如果你希望沿用Assembly.Load()的调用方式,可以在项目的runtimeconfig.json文件中添加探测路径,告诉.NET Core去指定目录查找程序集:
{ "runtimeOptions": { "probing": { "privatePath": "." } } }
这里的privatePath设置为.表示应用基础目录,你也可以指定其他相对路径。不过这种方式有个限制:它只对依赖项加载生效,对于动态加载的场景,可靠性不如直接指定路径。
为什么原来的.NET Framework方式在Core里失效?
简单来说,.NET Framework的程序集加载器会自动在应用基目录、私有路径以及**全局程序集缓存(GAC)**里查找匹配的程序集;而.NET Core的默认加载逻辑更注重依赖的确定性,它只会去应用的依赖清单(比如.deps.json)里定义的位置、NuGet缓存目录,以及runtimeconfig配置的探测路径里查找,不会主动扫描应用基础目录下的所有dll。
内容的提问来源于stack exchange,提问作者ankush

