(1) Using the code below I get exactly 2 items in my containers of one and the same exported plugin and I wonder why:
(2) Additional question which I really cannot implement: How can I extend the framework to handle different plugin types (such as having several imports of different types, or one import that stores all plugins in a dynamic IEnumerable or so). I want to provide in my static wrapper class one generic method that returns the discovered plugin as a function of type and matching meta data.
The exported plugin (which resides in a separate dll and whose location is pointed to when the DirectoryCatalog
is built.
[Export(typeof(IPlugin))] //<---- If this line is commented out then only one item is imported (why?)
[PluginAttribute(typeof(StrategyPlugin_Test1), "StrategyPlugin", "Plugin1")]
public class StrategyPlugin_Test1 : IPlugin
{
public void DoSomething()
{
Console.WriteLine("I do something");
}
}
The following code defines the strongly typed meta data and imports as well as a static class that performs the MEF functions and is supposed to hold the discovered plugins:
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginAttribute : ExportAttribute
{
public Type PluginType { get; set; }
public string PluginGroupName { get; set; }
public string PluginName { get; set; }
public PluginAttribute(Type pluginType, string pluginGroupName, string pluginName) : base(typeof(IPlugin))
{
PluginType = pluginType;
PluginGroupName = pluginGroupName;
PluginName = pluginName;
}
}
public interface IPluginAttribute
{
Type PluginType { get; }
string PluginGroupName { get; }
string PluginName { get; }
}
public interface IPlugin
{
void DoSomething();
}
public class PluginDefinition
{
[ImportMany(typeof(IPlugin))]
public IEnumerable<Lazy<IPlugin, IPluginAttribute>> Plugins { get; set; }
public PluginDefinition()
{
}
}
Here the static class that wraps some of the core MEF stuff:
public static class PluginManager
{
private static PluginDefinition PluginDefinitions { get; set; }
static PluginManager()
{}
public static void Configure(PluginDefinition pluginDefinitions, IEnumerable<string> pluginDirectories)
{
AggregateCatalog aggregateCatalog = new AggregateCatalog(new DirectoryCatalog(pluginDirectories.FirstOrDefault()));
CompositionContainer container = new CompositionContainer(aggregateCatalog);
container.ComposeParts(pluginDefinitions);
//store plugin definition
PluginDefinitions = pluginDefinitions;
}
public static T GetPlugin<T>(string pluginName, string pluginGroupName) where T : class
{
//how to implement this given type of T could be any of the plugin types ...
//...provided for in an extended PluginDefinition class?
return null;
}
}
The reason behind the duplicate exports is the fact that you are deriving your custom export metadata attribute from ExportAttribute. This means that when you decorate a class member with PluginAttribute
, you do not need to add the ExportAttribute
. MEF will look for attributes assignable to ExportAttribute
and it will find one in your PluginAttribute
.
For the other question regarding plug-in types, MEF allows for multiple exports on the same type. You can have one export of type IPlugin and another more specialized like you were doing in your code:
[Export(typeof(IPlugin))] //<---- If this line is commented out then only one item is imported (why?)
[PluginAttribute(typeof(StrategyPlugin_Test1), "StrategyPlugin", "Plugin1")]
public class StrategyPlugin_Test1 : IPlugin
And then have different imports for each exported type. You can have an IEnumerable<IPlugin>
import and then on another property a StrategyPlugin_Test1
import.