Managed Extensibility Framework (MEF) 和 Managed AddIn Framework (MAF, aka System.AddIn) 似乎完成了非常相似的任务。根据这个 Stack Overflow 问题,MEF 是 System.Addin 的替代品吗?,您甚至可以同时使用两者。
您什么时候选择使用其中一个?在什么情况下你会选择两者一起使用?
Managed Extensibility Framework (MEF) 和 Managed AddIn Framework (MAF, aka System.AddIn) 似乎完成了非常相似的任务。根据这个 Stack Overflow 问题,MEF 是 System.Addin 的替代品吗?,您甚至可以同时使用两者。
您什么时候选择使用其中一个?在什么情况下你会选择两者一起使用?
我一直在评估这些选项,这是我得出的结论。
MAF 是一个真正的插件框架。您可以完全分离您的插件,甚至在单独的应用程序域中运行它们,这样如果插件崩溃,它不会关闭您的应用程序。它还提供了一种非常完整的方法,可以将插件与除您提供的合同之外的任何内容分离。事实上,您可以在升级主应用程序时对您的合约适配器进行版本化,以提供对旧插件的向后兼容性。虽然这听起来不错,但要跨越应用程序域,您必须付出沉重的代价。您为速度以及可以来回发送的类型的灵活性付出了这个代价。
MEF 更像是依赖注入,具有一些额外的好处,例如可发现性和......(在这个上画一个空白)。MAF 的隔离程度在 MEF 中不存在。它们是针对两种不同事物的两种不同框架。
Danielg 说的很好。我要补充:
如果您观看有关 System.Addins 的视频,他们显然在谈论非常大的项目。他谈到一个团队管理主机应用程序,另一个团队管理每个插件,以及第三个团队管理合同和管道。基于此,我认为 System.Addins 显然适用于更大的应用程序。我正在考虑诸如 SAP 之类的 ERP 系统之类的应用程序(可能没有那么大,但你明白了)。如果您观看了这些视频,您会发现使用 System.Addins 的工作量非常大。如果您有很多公司为您的系统编写 3rd 方加载项,并且您不能违反任何这些加载项合同,那么这将很有效。
另一方面,MEF 似乎与 SharpDevelop 的插件方案、Eclipse 插件架构或 Mono.Addins 有更多相似之处。它比 System.Addins 更容易理解,而且我相信它更灵活。您失去的东西是您没有使用 MEF 获得 AppDomain 隔离或强大的版本控制合同。MEF 的优势在于您可以将整个应用程序构建为部件的组合,因此您可以为不同的客户提供不同配置的产品,如果客户购买了新功能,您只需将该功能的部件放到他们的安装目录中应用程序看到它并运行它。它也有利于测试。您可以实例化您想要测试的对象,并为其所有依赖项提供模拟对象,
我要提到的最重要的一点是,尽管 System.Addins 已经在框架中,但我没有看到很多人使用它的证据,但 MEF 只是坐在 CodePlex 上,据说应该包含在.NET 4,人们已经开始使用它构建大量应用程序(包括我自己)。我认为这可以告诉您有关这两个框架的一些信息。
开发并发布了 MAF 应用程序。我对 MAF 的看法有些厌烦。
MAF 在最坏的情况下是一个“去耦合”系统或“松耦合”系统。MEF 充其量是“耦合”系统或“松散耦合”系统。
我们通过使用 MAF 实现的 MAF 好处是:
在应用程序运行时安装新组件或更新现有组件。可以在应用程序运行时更新插件,并且更新会无缝地呈现给用户。为此,您必须拥有 AppDomains。
基于购买的组件的许可。我们可以控制用户的角色和权限加载了哪些 AddIn,以及该 AddIn 是否获得使用许可。
快速开发(更快的上市时间)。插件开发与敏捷方法完美契合,开发团队一次开发一个插件,而无需同时开发与应用程序其余部分的集成部分。
改进的 QA(一次仅 QA 一个组件)。然后,QA 可以针对单个功能测试和发布缺陷。测试用例更容易开发和实施。
部署(在开发和发布时添加组件并且它们“正常工作”)。部署只是制作插件和安装文件的问题。无需考虑其他因素!
新组件与旧组件一起工作。早期开发的插件继续工作。新插件无缝融入应用程序
在我看来,这两种技术实际上针对的是非常不同的用例。
MEF 通常最适合纯依赖注入场景,其中交付最终集成解决方案的个人或团队正在组装所有内容并保证整体完整性,但需要对关键功能进行不同的实现。
MAF 适用于某人/组正在开发平台或主机,而其他组将在事后以不受主机组控制的方式添加功能的场景。在这种情况下,需要更精细的机制来“保护”主机免受恶意插件的侵害(或相互保护插件)。
第三种类似模式的技术是整个 ProviderBase 方案。这也可以替换功能,但它的目标实际上是主机/应用程序绝对需要功能并且需要通过配置指定不同的实现。
我刚刚发现这篇讨论 MAF 和 MEF 的冗长文章。 http://emcpadden.wordpress.com/2008/12/07/managed-extensibility-framework-and-others/
除了其他答案提出的观点之外,MEF 和 MAF 之间的主要区别之一似乎是托管可扩展性框架将允许一个可组合部分依赖于另一个。例如,它会让一个插件依赖于另一个插件。
托管可扩展性框架也不像 System.AddIn 那样真正区分主机和外接程序。就 MEF 而言,它们都只是可组合的部分。
在我看来,发现差异的最好方法是一些动手代码。我找到了两个 MSDN 演练,都带有一个计算器示例,因此您可以轻松比较它们的实现:
MEF: 使用MEF 部件的简单计算器示例
(管理的可扩展性框架)
catalog.Catalogs.Add(new DirectoryCatalog("Plugins", "*.dll"));
(但您可以通过使用而不是使用来简单地修改示例
catalog.Catalogs.Add(new
AssemblyCatalog(typeof(Program).Assembly));
并提取计算器代码和合同以分离 DLL 项目。)MEF不需要特定的目录结构,使用起来简单直接,即使对于小型项目也是如此。它与属性一起使用,以声明导出的内容,易于阅读和理解。例子:
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '+')]
class Add: IOperation
{
public int Operate(int left, int right)
{
return left + right;
}
}
MEF 不会自动处理版本控制
MAF:带有 V1和 V2 版本MAF 插件
的
简单计算器(管理的插件框架)
Pipeline AddIns CalcV1 CalcV2 AddInSideAdapters AddInViews Contracts HostSideAdapters
MEF 和 MAF 都包含在 .NET Framework 4.x 中。如果您比较这两个示例,您会注意到与 MEF 框架相比,MAF 插件的复杂性要高得多——因此您需要仔细考虑何时使用这些框架中的哪一个。
MAF 和 MEF 都可以使用 AppDomain,并且都可以在运行时加载/卸载 dll。但是我发现的区别是:MAF 插件是解耦的,MEF 组件是松耦合的;MAF “激活”(新实例),而 MEF 默认生成实例。
使用 MEF,您可以使用泛型为任何合同制作 GenericHost。这意味着 MEF 加载/卸载和组件管理可以在一个通用库中并通用。