Search code examples
c#dynamicpluginsmef

Loading plugins at runtime with 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.


Solution

  • 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.