(1)使用下面的代码,我在一个和相同的导出插件的容器中得到2个项目,我想知道为什么:
(2)另外一个问题,我真的不能实现:我如何扩展框架来处理不同的插件类型(比如有几个不同类型的导入,或者一个导入存储所有插件在一个动态IEnumerable等)。我想在静态包装器类中提供一个泛型方法,该方法将发现的插件作为类型和匹配元数据的函数返回。
导出的插件(它驻留在一个单独的dll中,并且在构建DirectoryCatalog
时指向其位置)。
[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");
}
}
下面的代码定义了强类型元数据和导入,以及一个执行MEF函数的静态类,它应该保存发现的插件:
[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()
{
}
}
这里的静态类包装了一些核心的MEF内容:
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;
}
}
重复导出的原因是您正在从ExportAttribute派生自定义导出元数据属性。这意味着当你用PluginAttribute
装饰一个类成员时,你不需要添加ExportAttribute
。MEF将查找可分配给ExportAttribute
的属性,它将在您的PluginAttribute
中找到一个。
对于关于插件类型的另一个问题,MEF允许在同一类型上进行多个导出。你可以有一个IPlugin类型的导出和另一个更专业的导出,就像你在代码中做的那样:
[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
然后对每个导出类型有不同的导入。您可以使用IEnumerable<IPlugin>
导入,然后在另一个属性上使用StrategyPlugin_Test1
导入。