MEF 和单独的接口组件导致“每个类的接口”

Posted

技术标签:

【中文标题】MEF 和单独的接口组件导致“每个类的接口”【英文标题】:MEF & separate Interface assembly leads to "Interface for every class" 【发布时间】:2011-01-22 10:50:06 【问题描述】:

尤其是 DI/IoC 和 MEF,我的脚都湿透了。

我有一个 Web 应用程序,它有两种类型的部分(也许有一天会更多),这些部分由需要访问整个环境的接口定义。该应用程序有一个列表,其中包含由 MEF 组成的每种类型的具体实现。

环境包括:

几个存储库 当前应用请求 渲染引擎 导航引擎 加上一些静态实用程序类

如何将接口定义放在单独的程序集中,同时指定环境注入?

显然,我不能只引用主程序集,因为它需要引用合同程序集,而我无法创建循环引用。

看来我需要为每个环境类创建一个接口,以及它们的公开可用类型等等......必须有更好的方法吗?!

也许我也错过了这里明显的更大缺陷,如果有人可以为我指出吗?

【问题讨论】:

【参考方案1】:

如果您想将抽象与其实现分离(始终是一个有价值的目标),您应该在它们自己的程序集中定义这些抽象。

从实现方面来说,这很容易处理,因为您需要引用抽象来实现它们。无论您是否使用 MEF,都无法解决这个问题,所以一直都是这样:

[Import(typeof(IFoo))]
public class MyFoo : IFoo  

但是,正如您所说,这意味着您无法从抽象库中引用您的 Composition Root。然而,这是应该的,因为抽象不应该担心它们是如何组合的。

换句话说,您必须在抽象库之外实现依赖项的组合。一个很好的候选者是可执行文件本身,而您会将所有具体实现保存在一个或单独的库中。

抽象库将没有引用,而消费者和实现者都需要引用它,因此依赖关系图可能如下所示:

Composition Root --> Abstractions <-- Implementations

箭头表示参考。

【讨论】:

“无法从抽象库中引用您的组合根” - 这是目标,也是我困惑的根源。如果我的抽象有一个“Engine”类型的属性,它是在我的实现库中定义和实现的,我是否也需要在抽象库中为这种类型创建一个接口“IEngine”?现在,如果我有多个类型需要引用,每个类型都有自己的依赖项,我需要将所有这些抽象到抽象库中,不是吗? 是的,没错。所有这些额外的接口可能看起来开销很大,但实际上每个接口都是一个 Seam,您可以在其中将实现者与消费者分离。最终结果是一个更松散的耦合系统。好处可能不会立即明显,但是一旦您开始体验使用和公开抽象而不是具体类型的力量,您将永远不想回去:) 谢谢,所以我认为太多了,实际上完全没问题并且需要! 阿门——一旦我发现了抽象和接口的秘密,我就会到处使用它们。 我还没有找到组合根的样例。我看到很多帖子都说“在你的作文根中”等,但从来没有给那些正在学习 DI 并且以前从未见过 CR 的人提供任何示例或指导。

以上是关于MEF 和单独的接口组件导致“每个类的接口”的主要内容,如果未能解决你的问题,请参考以下文章

接口应该放在单独的包中吗? [关闭]

在WPF MVVM中导入使用MEF时不工作

使用 MEF 传递参数/属性

使用dynamic和MEF实现轻量级的AOP组件 ---- 系列文章

IOC之--MEF框架

MEF插件架构上的“即发即弃”方法