.NET5+环境下Prism WPF模块间接依赖解析问题咨询
Prism 8在.NET 5+环境下无法自动加载模块间接依赖问题
问题背景
将基于Prism开发的WPF应用从.NET Framework 4.7迁移至.NET 5平台时,先后在无.NET 5适配版本的Prism 4、已官方支持.NET 5的Prism 8中复现模块间接依赖加载异常。
简化后的依赖结构如下:
- ModuleA 依赖 EventsLib
- ModuleB 依赖 EventsLib
- 主应用负责配置、加载ModuleA与ModuleB
模块加载实现逻辑:通过XML文件定义待加载模块的程序集与类型名称,封装为ModuleInfo实例传入模块目录,所有相关二进制文件均存放于同一应用目录下。
现象差异
- .NET Framework 4.7环境:无需编写额外代码即可正常加载间接依赖EventsLib,ModuleA与ModuleB中的类型均可正常解析。
- .NET 5环境:启动时抛出
ModuleTypeLoaderNotFoundException异常,触发点为Prism.Modularity.ModuleManager.GetTypeLoaderForModule方法。
根因排查
查阅Prism源码确认:.NET 5环境下加载模块类型调用的Type.GetType()方法仅会加载应用deps.json文件中列出的依赖,不会自动加载未登记的间接依赖,直接导致模块化加载机制失效,该结论与.NET Framework、.NET Core/.NET 5+程序集加载机制的官方差异说明一致。
当前临时解决方案
仅针对.NET 5及以上目标框架生效:
- 在自定义模块目录的初始化逻辑中,注册程序集解析事件处理器:
#if NET5_0_OR_GREATER System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += OnResolving; #endif
- 在解析事件处理器中,从应用本地目录加载请求的程序集,针对资源程序集补充特殊处理逻辑:
private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName) { if (this.failedAssemblies.Contains(assemblyName.Name)) { return null; } if (assemblyName.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { return this.LoadResourceAssembly(loadContext, assemblyName); } string assemblyRootPath = System.AppDomain.CurrentDomain.BaseDirectory; var assemblyPath = System.IO.Path.Join(assemblyRootPath, assemblyName.Name) + ".dll"; var assembly = this.LoadAssemblyFromPath(loadContext, assemblyPath); if (assembly == null) { this.failedAssemblies.Add(assemblyName.Name); } return assembly; }
核心疑问
Prism 8已官方支持.NET 5,是否可通过特定配置启用框架内置的程序集解析机制,还是必须在自定义模块目录中手动实现程序集解析逻辑,才能正常加载模块的间接依赖?
回答
结论先行:Prism 8及以上版本没有内置针对未纳入deps.json的松散模块间接依赖的自动解析能力,不存在可一键开启的内置配置项,你目前实现的Resolving事件挂载方案是官方认可的标准处理方式,可以直接作为正式方案使用。
具体说明如下:
- 该问题不属于Prism的适配缺陷:Prism的模块类型加载完全依赖运行时提供的
Type.GetType()能力,.NET Core/.NET 5+ 从设计上取消了.NET Framework时代AppDomain自动探测应用目录加载未引用依赖的行为,默认仅加载启动阶段deps.json中登记的依赖项,这是运行时层面的机制变更,Prism作为上层框架不会篡改运行时的默认加载规则。 - 你当前实现的方案是动态加载场景下的通用解法:在默认程序集加载上下文的
Resolving事件中补充目录探测逻辑,配合失败程序集缓存、资源程序集特殊处理,完全符合.NET 5+的程序集加载规范,不存在兼容性风险。 - 如果不想手动实现解析逻辑,只能放弃松散模块的部署灵活性:将所有模块、间接依赖都作为主应用的直接项目引用,构建时主应用会自动把所有依赖信息写入
deps.json,运行时就可以自动解析所有依赖,但这种方式下模块无法独立更新、动态增减,失去了Prism模块化架构的核心优势。 - 补充说明:Prism自带的
DirectoryModuleCatalog仅实现了目录下模块程序集的枚举加载,不会递归解析模块的间接依赖,替换成这个目录类也无法解决该问题,仍然需要补充依赖解析逻辑。
内容的提问来源于stack exchange,提问作者unstone
相关产品推荐
相关产品推荐

