.NET 中类似插件的架构

发布于 2024-08-31 22:17:18 字数 628 浏览 2 评论 0原文

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

出现了几个问题:

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

是否有专门讨论此类 .NET 设计的书籍?

谢谢

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

I'm trying to implement a plug-in like application. I know there are already several solution out there but this is just going to be proof of the concept, nothing more. The idea would be to make the application main application almost featureless by default and then let the plugins know about each other, having them have implement all the needed features.

A couple of issues arise:

  1. I want the plugins at runtime to know about each other through my application. That wouldn't mean that at code-time they couldn't reference other plugin's assemblies so they could use its interfaces, only that plugin-feature initialization should be always through my main app. For example: if I have both plugins X and Y loaded and Y wants to use X's features, it should "register" its interest though my application to use its features. I'd have to have a kind of "dictionary" in my application where I store all the loaded plugins. After registering for interest in my application, plugin Y would get a reference to X so it could use it. Is this a good approach?
  2. When coding plugin Y that uses X, I'd need to reference X's assembly, so I can program against its interface. That has the issue of versioning. What if I code my plugin Y against an outdated version of plugin X? Should I always use a "central" place where all assemblies are, having there always the up to date versions of the assemblies?

Are there by chance any books out there that specifically deal with these kinds of designs for .NET?

Thanks

edit: I think people are drifting away from the 2 questions I made. I can take a look at both MEF and #develop, but I'd like to get specifics answers to the questions I made.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

悍妇囚夫 2024-09-07 22:17:18

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

I recommend looking into MEF. This is a new way of doing plugins in .NET. It is the recommend way of doing new addins for VS2010, for example. I've not used it myself, but what I've looked into about it looks great. Adding this as an answer on prodding of others :)

赠佳期 2024-09-07 22:17:18

查看 System.AddIn 命名空间。它的级别比 MEF 低一些,因此应该为您提供所需的“自己实现”体验。

Look into the System.AddIn namespace. It's a little lower-level than MEF, and so should give you the "implement it myself" experience you're looking for.

_畞蕅 2024-09-07 22:17:18

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

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

There is a good book on building what you are looking for: Dissecting a C# Application: Inside SharpDevelop. Here's a link: http://www.icsharpcode.net/OpenSource/SD/InsideSharpDevelop.aspx

The SharpDevelop application is fully plugin-based and the book talks about how they built it, the pitfalls they faced, and how they overcame it. The book is freely available from the site, or you can buy it too.

毁我热情 2024-09-07 22:17:18

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

加载程序集

获取程序集公开的类型

Once I done it using this example. I loved it, but it was couple years ago, I think there might be better solutions now. As long as I remember the basic idea was that there is abstract class in your program, and your plug-ins inherit that class and compiled as DLLs... or something similar using Interfaces. Anyways that approach worked great for me. Later I added a filesystemwatcher so it could load those DLL plugins while it is running.

To load an Assembly

To get the types the assembly exposes

羁绊已千年 2024-09-07 22:17:18

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

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

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

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

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

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

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

About the two specific issues you exposed:

1) I'm not sure what are you trying to achieve, but my guess is that you want to have lazy initialization of features, and maybe lazy loading of add-ins. If that's the goal, what you are proposing might work. So it could work like this:

  • The Y plugin provides a list of features it needs to use (it could be done for example through a specific interface implementation or through an xml manifest).
  • The X add-in implements an API which allows initializing a feature, with a method like Initialize(featureId).
  • The host application gets the feature list required by Y, loads/initializes the X plugin, and calls Initialize for each feature.
  • The host application also provides a GetFeature() method which Y can use to get a reference to a 'feature' object, which would be implemented in X.

However, if the plugin Y has direct access to the X API, I think it is unnecessary to have all that infrastructure for registering features. Y can just access the X features by directly using the X API, and Y would take care of lazy initializing each feature when required. For example, Y could just call SomeXFeature.DoSomething(), and the implementation of that class would initialize the feature the first time it is used.

2) If the API of an assembly changes, any assembly depending on it may break. Plugins are just assemblies which depend on other assemblies, so they will also break. Here are some things you can do to alleviate this problem.

  • Assign a version number to each plugin. This could be just the assembly version.
  • When loading a plugin, ensure that all dependencies can be properly satisfied (that is, all plugins on which it depends must be present and have the required version). Refuse to load the plugin if dependencies can't be satisfied.
  • Implement a plugin management tool, to be used for all plugin install/uninstall operations. The manager can check dependencies and report errors when trying to install plugins with unsatisfied dependencies, or when trying to uninstall a plugin on which other plugins depend.

Similar solutions are used by the Mono.Addins framework. In Mono.Addins, each add-in has a version number and a list of add-ins/versions on which it depends. When loading an add-in, the add-in engine ensures that all dependent add-ins with the correct versions are also loaded. It also provides an API and a command line tool for managing the installation of add-ins.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文