选择MEF和MAF(System.AddIn)之间的区别。

168

托管可扩展性框架(MEF)和托管AddIn框架(MAF,又称System.AddIn)似乎完成非常相似的任务。根据这个Stack Overflow问题(Is MEF a replacement for System.Addin?),你甚至可以同时使用两者。

何时选择使用一个而不是另一个?在什么情况下会选择同时使用两个?

7个回答

138

我已经评估了这些选项,以下是我的结论。

MAF是一个真正的插件框架。你可以将插件完全分离,甚至在一个单独的应用程序域内运行它们,这样如果插件崩溃,它也不会使你的应用程序崩溃。它还提供了一种非常完整的方法,通过依赖给定的合同来解耦插件。事实上,你可以版本化你的合同适配器,为旧的插件提供向后兼容性,同时升级主应用程序。虽然这听起来很好,但你必须付出沉重的代价才能跨应用程序域。你不仅要付出速度方面的代价,还要付出你可以来回发送的类型灵活性方面的代价。

MEF更像是带有一些附加优势(如可发现性和...(对此我没有想法))的依赖注入。MAF具有的隔离程度在MEF中并不存在。它们是两个不同的框架,针对两个不同的问题。


6
一个小细节:请记住,如果您的插件在本机层崩溃,'separate appdomain'是无济于事的,为此您仍需要工作进程。MAF在创建它们方面有所帮助,但从这样的崩溃中动态恢复仍然相当困难(但可能)。 - quetzalcoatl
@Ian:请重新阅读我的评论 :) 我确切地写了那个,并且更多:MAF 确实允许这样做,但是你必须自己在崩溃后重新站起来。 - quetzalcoatl
@DanielG >这是因为你必须支付沉重的代价才能跨越应用程序域< 为什么会这样?这个代价有多“沉重”? - Martin Meeser
2
@MartinMeeser 当跨越应用程序域时,您必须序列化所有内容或使用MarshalByRef对象。通信比在同一应用程序域中的对象之间交谈要困难得多。 - Danielg
现在MAF仍然被广泛使用吗? - Shimmy Weitzhandler

67

Danielg说的很好。我想补充一下:

如果您观看System.Addins的视频,会发现他们明显在谈论非常大的项目。他谈到一个团队管理主机应用程序,另一个团队管理每个AddIn,第三个团队管理合同和管道。基于此,我认为System.Addins显然适用于更大型的应用程序。我考虑的是像SAP这样的ERP系统(也许不是那么大,但您可以理解这个想法)。如果您观看了那些视频,您会发现使用System.Addins的工作量非常大。如果您有很多公司为您的系统编写第三方插件,并且不能违反任何这些插件合同,则它将有效。

另一方面,MEF似乎与SharpDevelop的插件方案、Eclipse插件架构或Mono.Addins更相似。比起System.Addins,它更容易理解,并且我认为它更加灵活。您失去的东西是,您不能使用MEF获得AppDomain隔离或强版本合同。 MEF的优点是,您可以将整个应用程序结构化为部分组成,因此您可以针对不同的客户以不同的配置来发布产品,如果客户购买了新功能,您只需将该功能的部件放入其安装目录中,应用程序就会看到它并运行。它还有助于测试。您可以实例化要测试的对象,并为其所有依赖项提供模拟对象,但是当作为组合应用程序运行时,组合过程会自动将所有真实对象连接在一起。

我想提出的最重要的一点是,即使System.Addins已经是框架的一部分,但我没有看到很多人使用它,但是MEF只是坐在CodePlex上,据说将包含在.NET 4中,而人们已经开始使用它来构建大量应用程序(包括我自己)。我认为这告诉您一些关于这两个框架的事情。


1
如果您观看有关System.Addin的视频,那么是哪些视频呢?请问能提供链接吗?谢谢。 - jimjim
1
@Arjang - 在 Channel 9 上有几个视频。请尝试访问 http://channel9.msdn.com/Blogs/DanielMoth/Managed-AddIn-Framework - Chris Spicer

61

我曾经开发并发布过一个MAF应用,因此我的MAF观点有些偏见。

MAF是一个“解耦合”系统或者最差的情况下是“松耦合”系统。而MEF则是一个“耦合”系统或者最好的情况下是“松耦合”系统。

使用MAF所获得的好处有:

  1. 在应用程序运行中安装新组件或更新现有组件。AddIn可以在应用程序运行时进行更新,更新对用户来说是无缝的。这需要AppDomains的支持。

  2. 基于购买的组件进行许可控制。我们可以根据用户的角色和权限以及AddIn是否获得许可来控制加载哪些AddIn。

  3. 快速开发(更快的上市时间)。AddIn开发与敏捷方法学非常匹配,开发团队一次只开发一个AddIn,而不必同时开发与应用程序的集成部分。

  4. 改进的QA(仅测试单个组件)。然后QA可以测试和报告单个功能位的缺陷。测试用例更易于开发和实施。

  5. 部署(随着开发和发布加入组件,它们“只需工作”)。部署只涉及创建AddIn并安装文件。不需要考虑其他因素!

  6. 新组件与旧组件兼容。早期开发的AddIn仍然可以正常工作。新的AddIn可以无缝地融入应用程序中。


3
我已经在.NET 4上使用MEF完成了以上所有操作,并且我认为它比MAF更简单。 - Tim
22
@Jim:您能在运行时卸载现有的MEF插件吗?据我所知,由于插件装配程序位于同一AppDomain中,一旦加载,插件装配程序就无法被卸载。 - Scott Whitlock
6
另一个未在这里列出的好处:您可以使用MAF对addin的安全权限进行沙盒化,而MEF中组件所使用的安全权限将与运行应用程序共享相同的权限。 - Doug
2
@ScottWhitlock: 你暗示了使用MEF与多个应用程序域是不可能的,这是不正确的。 - M.Stramm

28

在我看来,这两种技术实际上面向完全不同的应用场景。

MEF通常在纯依赖注入的场景下表现最佳,其中交付最终集成解决方案的人或团队正在组装一切并为整体完整性提供担保,但需要具有关键功能的不同实现。

MAF适用于一个场景,即某些人或团队正在开发平台或主机,其他团队将在事后以不在主机团队控制范围内的方式添加功能。在这种情况下,需要更复杂的机制来“保护”主机免受流氓插件的影响(或者保护插件彼此之间的影响)。

第三个类似模式的技术是整个ProviderBase方案。这也使替换功能成为可能,但它的目标实际上是主机/应用程序绝对需要某种能力,而需求实际上是通过配置指定不同的实现。


18
我刚刚发现了这篇长文,讨论了MAF和MEF。 http://emcpadden.wordpress.com/2008/12/07/managed-extensibility-framework-and-others/ 除了其他答案提到的点,听起来MEF和MAF之间的一个关键区别是,托管可扩展性框架允许一个可组合部件依赖于另一个。例如,它可以让一个插件依赖于另一个插件。
托管可扩展性框架也不像System.AddIn那样区分主机和插件。对于MEF来说,它们都只是可组合部件。

10

我认为最好的发现差异的方法是亲手写一些代码。我找到了两个MSDN演示文稿,都有一个计算器示例,这样你可以轻松比较它们的实现:

MEF: 使用MEF部件的简单计算器示例
(Managed Extensibility Framework)

展示如何使用MEF技术构建一个简单的计算器。不显示如何加载外部dll文件。(但是您可以通过使用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 插件的简单计算器
(Managed Addin Framework)

  • Shows how to build up the calculator by using a V1 plugin and then how to move over to a V2 plugin while maintaining backwards-compatibility (note: you can find the V2 version of the plugin here, the link in the original article is broken)
  • MAF enforces a specific directory structure, and it needs a lot of boilerplate code to make it work, hence I don't recommend it for small projects. Example:
    Pipeline
      AddIns
        CalcV1
        CalcV2
      AddInSideAdapters
      AddInViews
      Contracts
      HostSideAdapters
    

MEF和MAF都包含在.NET Framework 4.x中。如果你比较这两个例子,你会注意到MAF插件比MEF框架更加复杂 - 所以在使用这些框架时需要仔细考虑。


3

MAF 和 MEF 都可以使用 AppDomains 并且都能在运行时加载/卸载 dll。然而,我发现它们之间的区别是:MAF AddIns 是解耦的,MEF 组件是松耦合的;MAF "激活"(新实例),而 MEF 默认通过实例化来创建。

使用 MEF,您可以使用泛型为任何契约制作 GenericHost。这意味着 MEF 的加载/卸载和组件管理可以在一个通用库中使用泛型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接