使用 MEF 在运行时加载插件

发布于 2024-09-11 00:36:04 字数 836 浏览 2 评论 0原文

我的应用程序允许用户编写可以在运行时实例化的插件(实现 IPlugin)。启动时,会解析插件 .dll 目录,注册所有可用的插件信息。在运行时,提供了一个 GUI,允许用户创建任何插件的实例。这很好用。

但现在我看到 MEF 并希望我能做同样的事情,但以更优雅的方式编码。

到目前为止我使用 MEF 所做的工作:在启动时,我正在导入目录中的所有插件(导出 IPlugin)并读出名称、类别、作者等信息...这些被编码为插件类的导出元数据属性。导入是惰性完成的,因此所有插件都不会在启动时实例化,这一点很重要。

问题是,现在我没有找到一种在运行时优雅地实例化所选插件的方法,因为插件构造函数是一个导入构造函数,它导入对 IPluginHost 的引用(它是需要立即进行一些初始化)。

我在启动期间将相应的导出与插件信息一起保存在字典中,因此当 GUI 要求实例化给定特定插件信息的插件时,我可以访问导出(其中 Export.Value 是我的实际 IPlugin)。但是从那里我如何创建插件的实例并将其与 IPluginHost 组合在一起?

我认为我应该编写自己的 ExportProvider,每当有人要求时它都会为 IPluginHost 提供服务,但我无权访问程序集或特定插件的类型,无法将其添加到目录中,添加目录和 ExportProvider到一个容器并在该容器上调用 .ComposeParts。

我希望我已经清楚地说明了我的问题,如果没有,让我尝试一个问题的简短版本: MEF 有一个在启动时延迟加载插件以解析可用插件信息,然后在运行时根据特定插件信息创建特定实例的程序,这不是 MEF 的标准用例吗?如果能获得所涉及步骤的代码大纲就太好了。

My application allows users to write plugins (implementing IPlugin) that they can instantiate at runtime. On startup a directory of plugin .dlls is parsed, registering all the available plugins information. At runtime a GUI is provided that lets users create instances of any of the plugins. This works fine.

But now I see MEF and hope I can do the same, but in a more elegant way codewise.

What I got working so far with MEF: on startup I am doing an import of all plugins in a directory (that export IPlugin) and read out the information like name, category, author, etc... These are encoded as exported metadata attributes to the plugin classes. The import is done lazyly so all the plugins are not instantiated on startup, which is important.

The problem is that now I don't see a way to elegantly instantiate a selected plugin at runtime given the additional complication that the plugins constructor is an importing constructor which is importing a reference to an IPluginHost (which it needs immediately to do some initialization).

Together with a plugininfo I save the respective Export in a dictionary during startup, so when the GUI asks to instantiate a plugin given a specific plugininfo I have access to the Export (where Export.Value is my actual IPlugin). But from there how can I create an instance of the plugin and have it composed with the IPluginHost?

I gather I should write my own ExportProvider that serves the IPluginHost whenever someone asks for it, but I don't have access to the assembly or the type of the specific plugin that would let me add it to a Catalog, add the catalog and ExportProvider to a container and call .ComposeParts on that container.

I hope I made my problem clear, if not, let me try a short version of the question:
isn't it a standard usecase for MEF to have a program that lazy-loads plugins on startup to parse the available plugins infos and then at runtime create specific instances given specific plugininfos? would be great to get a codeoutline of the steps involved.

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

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

发布评论

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

评论(2

不再见 2024-09-18 00:36:05

如果我理解正确,您正在寻找一种动态创建多个插件实例(可能是同一插件)的方法。

您需要声明 ExportFactory< 类型的导入;IPlugin,IPluginMetadata>,然后根据元数据选择正确的工厂。 ExportFactory.CreateExport 将处理 IPlugin 实例所需的任何导入,例如您提到的 IPluginHost

请注意,ExportFactory 仅存在于早期版本的 MEF silverlight 版本中。要获得桌面版本,您当前需要 codeplex 的最新版本(MEF 2 - 预览版 1)。通过构造函数导入 ExportFactory 还存在一个已知问题,因此请使用属性。

If I understand correctly, you are looking for a way to dynamically create multiple plugin instances, potentially of the same plugin.

You need to declare an import of the type ExportFactory<IPlugin,IPluginMetadata> and then select the correct factory based on the metadata. ExportFactory.CreateExport will take care of any imports required by the IPlugin instances, like the IPluginHost you mentioned.

Note that ExportFactory was only in the silverlight edition of MEF in earlier releases. To get it in the desktop edition, you currently need the latest version from codeplex (MEF 2 - Preview 1). There is also a known problem with importing ExportFactory via the constructor, so use a property.

清风疏影 2024-09-18 00:36:05

您创建了 CompositionContainer 了吗?您可以使用它来请求特定的插件类型并实例化它们。目录将帮助您实现这一目标。您可以聚合多个目录(使用 AggregateCatalog),然后将结果传递给 CompositionContainer 的构造函数。当您请求特定的 IPlugin 类型(只需跟踪导出的类型)时,您可以要求 CompositionContainer 为您实例化插件,它会自动为您执行构造函数注入。

Have you created a CompositionContainer yet? You can use it to request particular plugin types and get them instantiated. The catalogs will get you part of the way there. You can aggregate multiple catalogs (using the AggregateCatalog) then pass the result to the constructor of the CompositionContainer. When you request your specific IPlugin Type (just keep track of the Type of the export) and you can ask the CompositionContainer to instantiate the plugin for you and it will do the constructor injection for you automatically.

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