我刚刚在我的mef应用程序中找到了一个问题;问题是,我的[Import]
媒体资源中有[ImportMany]
而不是IEnumerable<IFoo>
。我开始想知道为什么。 MEF看到注射目标是“集合”并且可以确定需要集合而不是单个元素。至少Ninject是这样工作的。
有没有人了解为什么需要[ImportMany]
?我能想到的唯一原因是人们可能想要[Export(typeof(IEnumerable<IBar>)] public IEnumerable<Bar> { get; }
,但这真的是这个设计的原因吗?我敢打赌,我不是唯一一个调试过这种错误的人。
答案 0 :(得分:6)
它不一样;)
[Import]
表示您要根据合同导入单件。在MEF中,合约只是一个字符串,当您导入类型(如IEnumerable<IBar>
)时,您实际上是根据合同导入的,该合同只是该类型的名称。
在MEF中,基数非常重要,因此当您声明要导入符合所述合同的单个实例时,只能有一个单个来源。如果找到多个导出,则由于基数不匹配而抛出异常。
[Import]
功能不包含处理IEnumerable<T>
的特殊逻辑,因此从它的角度来看,它只是一个像其他一切一样的契约。
然而,[ImportMany]
属性尤其适用于弥合这一差距。它对所述合同的任何数量的出口都接受零。这意味着,您可以将{em>多个导出IEnumerable<IBar>
散布在多个程序集中,而不是{em>单导出IBar
,而且永远不会是基数不匹配。
最后它是一个设计哲学。 MEF可能有关于IEnumerable<T>
的特殊内置知识。 Autofac(显然是Ninject)就是这样做的,并称之为Relationship Type。
然而,像这样的特殊套管意味着实施代码某处违反Liskov Substitution Principle,这又会导致POLA违规,所以在这种情况下,我倾向于与MEF设计师站在一边。寻求更明确的API可能会降低可发现性,但可能会更安全一些。
答案 1 :(得分:2)
稍微简化上述答案:
[Import]
将抛出异常。[ImportMany]
将加载多个匹配的导出,而不会抛出错误。如果我有一个我要导入的IDataAccessLayer,那么应该只有一个导出可用 - 我永远不会同时写入2个数据库,所以我使用[Import]
来确保只存在一个
如果我想加载许多不同的BusinessObjects,我将使用[ImportMany]
因为我需要许多不同类型的BusinessObjects。