compositioncontainer 初始化失败常因类型反射加载失败,主因是程序集版本/框架不匹配、dll未显式加载或缺失部署依赖;import为null则多因catalog未包含对应export、路径错误或契约不一致。

为什么 CompositionContainer 初始化失败常报“Unable to load one or more of the requested types”
这通常不是 MEF 本身的问题,而是类型解析时反射加载失败。常见原因包括:引用的程序集版本不匹配、目标框架不一致(如插件编译为 .NET 5,宿主是 .NET 6)、或类型定义在未被 Assembly.LoadFrom 加载的 DLL 中。
- 确保所有参与组合的程序集都已通过
Assembly.LoadFrom或AppDomain.CurrentDomain.GetAssemblies()显式可用 - 避免在
[Export]类型中引用仅存在于开发机但未部署到运行环境的 NuGet 包(比如调试用的Microsoft.CodeAnalysis) - 使用
try/catch (ReflectionTypeLoadException ex)捕获并检查ex.LoaderExceptions,能快速定位具体哪个类型加载失败
Import 属性为 null?检查 ComposablePartCatalog 是否包含对应 Export
MEF 不会自动扫描整个程序集——它只从你显式提供的 ComposablePartCatalog 中查找导出项。如果你用了 DirectoryCatalog,但插件 DLL 没放对路径、没加扩展名、或被杀毒软件锁定,Import 就会保持 null。
- 用
catalog.Parts.Count()确认目录是否真读到了导出部件;若为 0,说明路径或程序集加载失败 -
DirectoryCatalog默认只识别.dll文件,不识别.exe或无扩展名文件 - 若导出类在主程序集中,别忘了用
AssemblyCatalog(Assembly.GetExecutingAssembly())显式加入 - 属性上必须有
[Import],且类型签名要和[Export]完全一致(含命名空间),接口导出需指定 contract name 才能按接口导入
用 ExportFactory<t></t> 替代直接 Import 实现延迟创建与生命周期控制
直接 [Import] 会导致对象在容器构造时就被实例化,无法控制创建时机,也无法释放资源。而 ExportFactory<t></t> 提供 CreateExport() 方法,每次调用都新建实例,并支持 Dispose()。
- 导出端写法:
[Export(typeof(IMyService))][PartCreationPolicy(CreationPolicy.NonShared)] - 导入端声明:
[Import] public ExportFactory<imyservice> ServiceFactory { get; set; }</imyservice> - 使用时:
using var export = ServiceFactory.CreateExport(); var service = export.Value; - 注意:若导出类实现了
IDisposable,且策略是NonShared,务必手动调用export.Dispose(),否则会泄漏实例
.NET Core/.NET 5+ 中为什么 System.ComponentModel.Composition 不推荐继续用
原生 MEF(即 System.ComponentModel.Composition)在 .NET Core 中只是兼容层,功能受限:不支持 DirectoryCatalog 的热重载、无法处理跨平台路径、反射行为与桌面版不一致,且微软已明确标记为“legacy”。新项目应迁移到 Microsoft.Extensions.DependencyInjection + 插件式设计,或使用社区维护的 MEF2(System.Composition)。
-
System.Composition是轻量级替代品,API 类似但不兼容旧 MEF,需替换命名空间、改用ContainerConfiguration构建容器 - 它的
AssemblyPartDiscovery支持更可控的类型筛选,避免误加载测试类或内部工具类 - 没有
Lazy<t></t>自动包装,需手动用Lazy<t></t>包裹ExportFactory实现延迟
Import 就是 null,还不会报错,只会静默失败。










