MEF中ImportDefinitions非空但Import属性失效,属性为何仍为null?
这种情况我碰到过好几次,明明看起来配置都对,但就是注入不进去,大概率是某个容易忽略的细节没做好,给你列几个排查方向:
确认Export类的构造函数是否符合MEF要求
你的IApiClient实现类如果有带参数的构造函数,MEF默认只会调用无参构造。如果构造函数需要依赖,要么给这些依赖也加上[Export]确保容器能找到,要么给构造函数标记[ImportingConstructor],明确告诉MEF使用这个构造函数来实例化。检查Import的基数(Cardinality)是否匹配
如果你用的是默认的[Import](要求必须有一个匹配的Export),但容器里存在多个IApiClient的Export,MEF会无法确定注入哪个,导致属性保持null。反过来,如果你的属性是集合类型(比如IEnumerable<IApiClient>),但用了[Import]而非[ImportMany],也会出问题。核对你的代码:// 单个实例的正确写法 [Import] public IApiClient ApiClient { get; set; } // 多个实例的正确写法 [ImportMany] public IEnumerable<IApiClient> ApiClients { get; set; }别忘了执行Composition操作
配置好CompositionContainer后,必须主动触发组合操作,让容器把Export注入到Import属性里。比如在MainWindow的构造函数里,你需要调用:container.ComposeParts(this);或者用
SatisfyImportsOnce:container.SatisfyImportsOnce(this);很多时候就是漏掉了这一步,导致容器没完成注入。
确保Export类和Import属性是公共可见的
MEF无法访问非公共的类型或成员:- 你的
IApiClient实现类必须是public的,internal或私有嵌套类即使加了[Export]也会被容器忽略; - 你的Import属性也必须是
public的,private/protected属性MEF无法注入。
- 你的
验证目录加载的程序集是否正确
虽然你说容器目录Parts非空,但要确认这些Parts里确实包含你的IApiClient实现类。比如如果Export在另一个程序集里:- 用
AssemblyCatalog的话,有没有传入正确的程序集实例? - 用
DirectoryCatalog的话,有没有包含该程序集的目录路径?
调试时可以查看container.Catalog.Parts里的类型,确认是你期望的实现类。
- 用
检查MEF的组合错误
MEF在组合失败时默认不会抛出异常,但会记录错误信息。你可以在组合后检查CompositionErrors集合,找出隐藏的问题(比如依赖缺失、类型不兼容等):var batch = new CompositionBatch(); batch.AddPart(this); container.Compose(batch); if (container.CompositionErrors.Any()) { foreach (var error in container.CompositionErrors) { // 输出错误信息,比如到控制台或日志 Console.WriteLine($"MEF组合错误:{error.Description}"); } }
内容的提问来源于stack exchange,提问作者Roman

