How to support dual versions of an interface in MEF?
I am managing a complex projects which share components through shared contracts. There are several hosts and many of these shared plugins.
In order to simplify compatibility and deployment, we are going to agree on two sets of interfaces: v(latest) and v(latest-1). Somehow, each host must support both sets.
Ideally, I'd like to write the host to target just the latest v(latest), and have the old components transparently adapted, by some custom adapter code that the v(latest) contract deve开发者_开发百科loper would be responsible for.
Host importing v(Latest) -> Adapter -> Plugin export v(Latest-1)
Is there any way I can achieve this in MEF? I'm not too familiar with its extensibility model yet, I've never used it before.
Instead of doing an ImportMany
of all the plugins, you could just import a IPluginProvider
. You could then put the necessary adapter logic inside the plugin provider implementation. For example:
[Export(typeof(IPluginProvider))]
public PluginProvider : IPluginProvider
{
[ImportMany]
public IEnumerable<IPlugin2> Plugins { get; set; }
[ImportMany]
public IEnumerable<IPlugin1> LegacyPlugins { get; set; }
public IEnumerable<IPlugin2> GetPlugins()
{
var adaptedPlugins = this.LegacyPlugins.Select(x => new Adapter(x));
return this.Plugins.Concat(adaptedPlugins);
}
}
This option only works if you have control over the plugin consumers, so that you can change them to import IPluginProvider
. If not, you'll need to set up your MEF container with an ExportProvider
implementation which is somehow aware of adapters.
MEF does not come with something like that out of the box, so I rolled my own experimental ExportManyProvider. It allows you to export adapter services like the one above with an ExportMany
attribute. See the test code for an example of how to use it.
精彩评论