You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET与.NET Framework动态加载程序集的传递解析差异

.NET 7与.NET Framework 4.6.1程序集加载行为差异原因分析

问题场景

面向.NET 7和.NET Framework 4.6.1的应用在CLR程序集加载行为上存在明显差异:
基于一套插件系统,核心是「参考控制台应用」,引用所有netstandard2.0类库,构建后发布到对应平台专属文件夹,其他应用通过该文件夹动态加载程序集。

复现项目架构:

  • TestContracts:netstandard2.0项目,暴露ITracer接口;
  • TestLibrary:netstandard2.0项目,依赖TestContracts实现Tracer类,同时依赖Elastic.Clients.Elasticsearch NuGet包,该包传递依赖System.Text.Json v8.0.5(对应程序集版本8.0.0.0);
  • TestReferenceApp:多目标net7.0和net461,引用TestContracts和TestLibrary,通过dotnet publish发布到PublishedAppNet70和PublishedAppNet461文件夹;
  • TestApp:入口项目仅依赖TestContracts,通过Assembly.LoadFrom从平台发布文件夹加载TestLibrary,实例化Tracer并转为ITracer接口。调用ITracer.Trace方法时,.NET 7版本抛出System.IO.FileLoadException(提示无法加载System.Text.Json 8.0.0.0),而.NET Framework 4.6.1版本运行正常。

差异核心原因

1. 程序集加载上下文的依赖搜索逻辑不同

  • .NET Framework 4.6.1的传统CLR中,Assembly.LoadFrom加载的程序集会被放入LoadFrom上下文,CLR会自动从该程序集的所在目录搜索其依赖项(包括传递依赖)。由于PublishedAppNet461目录已包含System.Text.Json.dll(发布时从NuGet包复制而来),因此加载时能直接找到。
  • .NET 7的CoreCLR中,Assembly.LoadFrom加载的程序集同样进入LoadFrom上下文,但CoreCLR不会自动将该程序集的目录加入依赖搜索路径,默认优先从TestApp的运行基目录查找依赖。而TestApp本身未引用System.Text.Json,因此无法找到对应的程序集。

2. 发布阶段的依赖复制规则差异

  • 针对.NET Framework 4.6.1的dotnet publish会默认将所有依赖程序集(包括NuGet传递依赖)复制到发布目录,确保PublishedAppNet461中存在System.Text.Json.dll。
  • 针对.NET 7的dotnet publish(默认框架依赖部署模式),虽然也会复制第三方依赖到发布目录,但由于CoreCLR的加载逻辑限制,TestApp运行时不会主动去PublishedAppNet70目录搜索该依赖,导致加载失败。

3. 程序集解析与绑定机制的区别

  • .NET Framework依赖绑定重定向机制,默认自动处理版本冲突,同时LoadFrom上下文的依赖查找逻辑会优先使用自身所在目录,进一步保证了依赖能被找到。
  • .NET 7移除了自动绑定重定向(需手动配置),且CoreCLR没有将LoadFrom上下文程序集的目录纳入全局搜索路径。若未通过AssemblyLoadContext.Resolving事件手动指定依赖加载路径,就会出现找不到依赖的异常。

内容的提问来源于stack exchange,提问作者Palo Mraz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:10:13