Multiple plugin type

Feb 23, 2010 at 10:21 AM

Hi, I'm working in a project where we need to allow the user to import different plugins that is plugin with different contracts.
The contracts are: IFilter, IFeature, IDimension and so on.
The MainViewModel has to expose a list for each plugin's contract type so:

IEnumerable<IFilter> Filters { get; set; }
IEnumerable<IFeature> Features { get; set; }
...

Then we have another ViewModel which uses IFilter plugins

How could I do?

Two ideas come to my mind in order to manage this system:

1) A plugin manager class which exposes a collection of IFilter, IFeature, so on
2) A plugin manager class which exposes a collection of IPlugin and the each ViewModel gets its plugins using metadata

Thanks
Federico

Feb 23, 2010 at 6:37 PM

Well firstly, inheriting from interfaces generally speaks bad design to me, you should reconsider your design. 

What I do is the latter approach, however I use protected internal classes to implement attributes with metadata for each type of plugin, in these specialized plugin attributes i embed the type info, then use the metadata mef collects to sort them out after they've been composed.

Feb 23, 2010 at 6:47 PM
Edited Feb 23, 2010 at 6:47 PM

Having a PluginManager which returns to each VM the plugins it needs is a resonable approach. The manager is a shared part which imports all of the plugins and their metadata (IEnumerable<Lazy<T,M>>. It then exposes a method like GetPlugins which accepts some sort of filter. The VMs access the plugin manager passing it whatever context they need to to get back the plugins they require.

Glenn

Feb 26, 2010 at 7:37 AM

Thanks!

Mar 3, 2010 at 1:52 PM

Hi :)
I've resolved in this manner:

I've created an IPluginManager interface

public interface IPluginManager
    {
        event EventHandler PluginsChanged;

        ICollection<string> PluginsName { get; set; }

        void AddPlugin(string plugin);
        void RemovePlugin(string plugin);
        T GetPlugin<T>() where T : class;
        IEnumerable<T> GetPlugins<T>() where T : class;
    }

Then I've registered the class MyPluginManager in the PRISM container and when a viewmodel needs to access a plugin, asks the container to resolve the IPluginManager

public FeatureExtractionMenuViewModel(IUnityContainer container)
        {
            this.container = container;
            this.pluginsManager = container.Resolve<IPluginManager>();
            this.LoadPlugins();
            this.pluginsManager.PluginsChanged += new EventHandler(pluginsManager_PluginsChanged);
        }

When the vm'll need one or more plugin, it calls GetPlugins<T>() or GetPlugin<T>()

pluginsManager.GetPlugins<BaseResultsSaver>()

where T is the plugin's type that it needs

I use a custom export attribute in order to discriminate the plugin type

[MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class ExportPluginAttribute : ExportAttribute, IPluginMetadata
    {
        public ExportPluginAttribute()
            : base(typeof(IPlugin))
        {
        }

        public Type PluginType { get; set; }
    }

MyPluginManager is implemented in this way http://codepaste.net/jo8vyc

What do you think?

Thanks for the support
Federico

PS: Sorry for my poor english