C#如何处理GetExportedTypes类型加载错误及实现类型加载重定向
解决方案
方案1:直接过滤加载失败的类型(最高优先级推荐)
原生GetExportedTypes在遇到无法加载的类型时会抛出ReflectionTypeLoadException,该异常的Types属性已经包含了所有成功加载的类型,仅加载失败的对应位置为null,你直接过滤掉空值即可得到所有可用类型,完全不需要处理缺失的无用类型:
Type[] validExportedTypes; try { validExportedTypes = targetAssembly.GetExportedTypes(); } catch (ReflectionTypeLoadException ex) { // 过滤加载失败的null项,保留所有成功加载的有效类型 validExportedTypes = ex.Types.Where(type => type != null).ToArray(); }
用获取到的validExportedTypes做序列化注册即可,完全不受缺失类型的影响。
方案2:自定义类型加载重定向
如果你确实需要伪造一个占位类型来满足加载逻辑,C#提供了和AssemblyResolve对应的TypeResolve事件,专门用于处理类型加载失败的场景,可以实现你要的类型重定向逻辑:
实现步骤:
- 在你的项目中定义一个和缺失类型完全限定名完全一致的占位类,命名空间、类名必须和缺失的类型完全相同,如果原类型有强命名要求,需要确保你的占位类所在程序集签名匹配,或者配置跳过强名称验证。
- 在程序启动阶段订阅
AppDomain.CurrentDomain.TypeResolve事件,在加载缺失类型时返回你定义的占位类型:
AppDomain.CurrentDomain.TypeResolve += (sender, args) => { // 判断当前加载失败的类型是否是你要替换的缺失类型 if (args.Name == "缺失类型的完全限定名, 缺失类型所在程序集的完全限定名") { // 返回你预先定义的伪造占位类型 return typeof(你定义的占位类); } return null; };
注意:C# 不需要像 C++ 一样保证内存布局一致,只要占位类的完全限定名匹配,且你不会实际调用该类型的任何成员,就不会引发运行时错误。
常见注意事项
- 如果你使用的是 .NET Core/.NET 5+ 版本,上述API完全兼容,无需额外调整
- 若原程序集有强签名,也可以通过配置文件的
assemblyBinding节点做程序集重定向,将原程序集的请求指向你存放伪造类型的自定义程序集
内容的提问来源于stack exchange,提问作者Victor Burckel
相关产品推荐
相关产品推荐

