【问题标题】:Plugin-like architecture in .NET.NET 中的插件式架构
【发布时间】:2010-05-07 21:48:36
【问题描述】:

我正在尝试实现一个类似插件的应用程序。我知道已经有几种解决方案,但这只是概念的证明,仅此而已。这个想法是让应用程序的主应用程序默认几乎没有功能,然后让插件相互了解,让它们实现所有需要的功能。

出现了几个问题:

  1. 我希望插件在运行时通过我的应用程序相互了解。这并不意味着在代码时他们不能引用其他插件的程序集,因此他们可以使用它的接口,只是插件功能初始化应该始终通过我的主应用程序。例如:如果我同时加载了插件 X 和 Y 并且 Y 想要使用 X 的功能,它应该通过我的应用程序“注册”它的兴趣以使用它的功能。我必须在我的应用程序中有一种“字典”,用于存储所有加载的插件。在注册对我的应用程序感兴趣后,插件 Y 将获得对 X 的引用,以便它可以使用它。这是一个好方法吗?
  2. 在编写使用 X 的插件 Y 时,我需要引用 X 的程序集,这样我就可以针对它的接口进行编程。那有版本控制的问题。如果我针对插件 X 的过时版本编写插件 Y 怎么办?我是否应该始终使用所有程序集所在的“中心”位置,始终保持最新版本的程序集?

是否有专门针对 .NET 的此类设计的书籍?

谢谢

编辑:我认为人们正在远离我提出的 2 个问题。我可以查看 MEF 和 #develop,但我想获得我提出的问题的具体答案。

【问题讨论】:

  • 我建议研究一下 MEF,它是全新的,但看起来很有前途。
  • @Matt - 认为你应该把这个作为答案 - 这正是我要说的
  • 我已经听说过 MEF,但正如 OP 中所述,我的想法不是使用已经构建的框架,而是自己实现它。它不需要非常复杂的东西。
  • @Matt - 添加您的答案。 MEF 是一个不错的选择,如果您也想了解“如何在 .net 中做插件”,它也是一个很好的起点。
  • 他不想使用 MEF。他想构建类似于 MEF 的东西。他在他的帖子中说得很清楚。

标签: c# .net plugins extensibility


【解决方案1】:

我建议查看MEF。这是在 .NET 中做插件的一种新方法。例如,这是为 VS2010 做新插件的推荐方式。我自己没有使用过它,但我对它的研究看起来很棒。将此添加为刺激他人的答案:)

【讨论】:

【解决方案2】:

查看System.AddIn 命名空间。它比 MEF 略低一些,因此应该为您提供您正在寻找的“自己实现”的体验。

【讨论】:

【解决方案3】:

有一本关于构建您正在寻找的内容的好书:剖析 C# 应用程序:SharpDevelop 内部。这是一个链接:http://www.icsharpcode.net/OpenSource/SD/InsideSharpDevelop.aspx

SharpDevelop 应用程序完全基于插件,书中讨论了他们如何构建它、他们面临的陷阱以及他们如何克服它。该书可从该网站免费获得,或者您也可以购买。

【讨论】:

    【解决方案4】:

    一旦我使用this example 完成它。我喜欢它,但那是几年前的事了,我认为现在可能有更好的解决方案。只要我记得基本思想是你的程序中有抽象类,你的插件继承该类并编译为 DLL ......或使用接口类似的东西。无论如何,这种方法对我很有用。后来我添加了一个文件系统观察器,这样它就可以在运行时加载那些 DLL 插件。

    To load an Assembly

    To get the types the assembly exposes

    【讨论】:

    • 正是我要说的。添加了一些指向感兴趣的 MSDN 页面的链接。
    • 是的,但这是一个简单的例子。只是基本的反射和简单的 OO 设计。
    • 是的...我建议的唯一原因是因为它能够解决您上面指定的问题...当然要努力...您必须编写复杂的插件管理器.如果您正在寻找开箱即用的东西,那么就像大家建议的那样使用 MEF……它似乎非常强大。
    【解决方案5】:

    关于你暴露的两个具体问题:

    1) 我不确定您要实现什么目标,但我猜您希望延迟初始化功能,并且可能延迟加载加载项。如果这是目标,那么您提出的建议可能会奏效。所以它可以像这样工作:

    • Y 插件提供了它需要使用的功能列表(例如,可以通过特定的接口实现或通过 xml 清单来完成)。
    • X 插件实现了一个 API,该 API 允许使用 Initialize(featureId) 之类的方法来初始化功能。
    • 宿主应用程序获取 Y 所需的功能列表,加载/初始化 X 插件,并为每个功能调用 Initialize
    • 宿主应用程序还提供了一个 GetFeature() 方法,Y 可以使用该方法来获取对“特征”对象的引用,该对象将在 X 中实现。

    但是,如果插件 Y 可以直接访问 X API,我认为没有必要拥有所有用于注册功能的基础设施。 Y 可以直接使用 X API 访问 X 功能,并且 Y 会在需要时负责延迟初始化每个功能。例如,Y 可以只调用 SomeXFeature.DoSomething(),该类的实现将在第一次使用该功能时对其进行初始化。

    2) 如果程序集的 API 发生变化,任何依赖于它的程序集都可能会中断。插件只是依赖于其他程序集的程序集,因此它们也会中断。您可以采取一些措施来缓解此问题。

    • 为每个插件分配一个版本号。这可能只是汇编版本。
    • 加载插件时,确保所有依赖项都能得到正确满足(即,它所依赖的所有插件都必须存在并具有所需的版本)。如果无法满足依赖关系,则拒绝加载插件。
    • 实现插件管理工具,用于所有插件安装/卸载操作。当尝试安装依赖不满足的插件,或者尝试卸载其他插件所依赖的插件时,管理器可以检查依赖并报告错误。

    Mono.Addins 框架使用了类似的解决方案。在 Mono.Addins 中,每个插件都有一个版本号和它所依赖的插件/版本列表。加载加载项时,加载项引擎确保同时加载所有具有正确版本的依赖加载项。它还提供了一个 API 和一个命令行工具来管理插件的安装。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 2011-05-24
      • 1970-01-01
      相关资源
      最近更新 更多