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

.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及以上目标框架生效:

  1. 在自定义模块目录的初始化逻辑中,注册程序集解析事件处理器:
#if NET5_0_OR_GREATER
System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += OnResolving;
#endif
  1. 在解析事件处理器中,从应用本地目录加载请求的程序集,针对资源程序集补充特殊处理逻辑:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:15:48