如何在MEF中避免未使用类型引发的TypeLoadException?
项目结构如下:
MyProject | | (Imports with MEF) | MyImplementation | | (has reference to) | ThirdPartyLib / \ / \ (has refs to) / \ USB.dll Bluetooth.dll
在开发/测试用的Windows 11机器上导入MyImplementation时一切正常,但在用户的Windows 10(版本1607)机器上出现以下异常:
System.TypeLoadException: Could not find Windows Runtime type 'Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristicsResult'.
System.TypeLoadException: Could not find Windows Runtime type 'Windows.Devices.Bluetooth.GenericAttributeProfile.GattDescriptorsResult'.
System.TypeLoadException: Could not find Windows Runtime type 'Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceServicesResult'.
查询得知这些类型仅在Win10 Build 15063及以上版本引入,而我并未使用蓝牙功能(推测这些类型由Bluetooth.dll使用)。直接引用ThirdPartyLib的示例程序可正常运行。我仅能控制MyProject和MyImplementation的代码,能否让MEF忽略这些异常完成组件组合?或是否可通过引入其他库填补缺失类型?
方案1:让MEF忽略类型加载异常完成组合
MEF默认加载组件时会严格检查所有依赖类型,可通过以下方式绕过:
- 用
AssemblyLoadContext隔离加载MyImplementation和ThirdPartyLib,注册TypeResolve事件,当遇到缺失的蓝牙相关类型时,返回一个空占位符类型,直接跳过类型加载错误。 - 自定义
ExportProvider扩展MEF的CompositionContainer,在组合过程中捕获TypeLoadException并继续处理其他导出项,不过这种方式需要熟悉MEF内部逻辑,实现复杂度较高。
方案2:避免触发蓝牙依赖加载
既然不需要蓝牙功能,可尝试切断蓝牙相关代码的加载路径:
- 检查
ThirdPartyLib是否有配置开关或条件编译选项来禁用蓝牙模块,若有,在MyImplementation初始化时传入禁用蓝牙的参数。 - 若
ThirdPartyLib是模块化拆分的强命名程序集,可尝试仅加载与USB功能相关的模块,避免触发蓝牙DLL的类型扫描。
方案3:填补缺失类型(不推荐)
这类WinRT类型是系统级API,第三方库无法提供完全兼容的实现,强行添加占位符类型会导致后续调用出现更隐蔽的运行时错误,不建议采用。
补充说明
直接引用ThirdPartyLib的示例程序能正常运行,是因为示例未触发蓝牙相关代码的JIT编译;而MEF加载组件时会扫描所有导出类型的依赖,触发了蓝牙DLL的类型检查。核心解决思路是阻止MEF扫描到蓝牙依赖,或在类型加载时忽略缺失项。
内容的提问来源于stack exchange,提问作者komodosp

