MEF,为什么创建同一个导出插件的相同副本?

时间:2013-05-07 09:04:55

标签: c# plugins reflection mef .net-assembly

(1)使用下面的代码我在我的容器中得到了两个相同的导出插件,我想知道为什么:

(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;
    }

}

1 个答案:

答案 0 :(得分:4)

重复导出背后的原因是您从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导入。