.NET 中类似插件的架构
我正在尝试实现一个类似插件的应用程序。我知道已经有几种解决方案,但这只是概念的证明,仅此而已。这个想法是让应用程序主应用程序默认情况下几乎没有功能,然后让插件相互了解,让它们实现所有需要的功能。
出现了几个问题:
- 我希望插件在运行时通过我的应用程序相互了解。这并不意味着在代码时他们无法引用其他插件的程序集,以便他们可以使用其接口,只是插件功能初始化应该始终通过我的主应用程序进行。例如:如果我加载了插件 X 和 Y,并且 Y 想使用 X 的功能,则它应该通过我的应用程序“注册”其兴趣以使用其功能。我的应用程序中必须有一种“字典”,用于存储所有加载的插件。注册对我的应用程序感兴趣后,插件 Y 将获得对 X 的引用,以便它可以使用它。这是一个好方法吗?
- 当编写使用 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:
- 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?
- 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议查看 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 :)
查看 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.有一本关于构建您正在寻找的内容的好书:剖析 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.
一旦我使用这个示例完成了它。我喜欢它,但那是几年前的事了,我认为现在可能有更好的解决方案。我记得基本思想是你的程序中有一个抽象类,你的插件继承该类并编译为 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
关于您暴露的两个具体问题:
1)我不确定您想要实现什么,但我的猜测是您想要延迟初始化功能,也许还需要延迟加载加载项。如果这是目标,那么您提出的建议可能会奏效。所以它可以像这样工作:
但是,如果插件 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:
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.
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.