MEF元数据确保类实现Metadata属性中声明的接口

时间:2012-05-22 11:02:44

标签: c# .net interface mef

您好我有一个检测元数据属性的MEF容器,我想扩展它并允许类实现其他接口(在下面的示例中,我想实现一个额外的接口IPluginSettings)。

模块GUID标识符非常重要,因为它与我的数据库应用程序中的模块ID进行了协调,如果我在MEF容器中查询导入的接口,我可以遍历它们:

foreach (Lazy<T,IPluginMetadata> moduleInAssembly in m_Container.GetExports<T, IPluginMetadata>();)
{
  T value = moduleInAssembly.Value; // instantiate an object of type T to test for implementations of other interfaces...
  if (value is IPluginSettings)
  {
      // this module also contains an interface for settings!
  }
  Guid moduleInAssemblyId = Guid.Parse(moduleInAssembly.Metadata.PluginID);
}

我有一些问题:

1)在上面的场景中,我必须实例化该类以测试它是否实现了特定的接口,是否有更好的方法使用Metadata执行此操作并增强PluginExportAttribute以接受辅助接口类型列表?< / p>

2)如何告诉MEF容器导入只有PluginExportAttribute的类型?

3)或者不是让每个插件界面灵活/自由地声明它自己的界面,我会更好的插件来实现一个众所周知的插件接口,其中包含一个工厂来实例化特定的插件接口? (我要问的例子是代码的底部 - 最后一节)

4)感谢一个建议的答案,我使用的代码按照下面的问题4 snipit结构,它的工作原理!出于好奇,无论如何都要将多个单独的Export属性合并到PluginExportAttribute中,也许在构造函数参数中要记录其他类型的注册?

谢谢,

克里斯

public interface IPluginMetadata
{
    string PluginID { get; }
}

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginExportAttribute : ExportAttribute, IPluginMetadata
{
    public PluginExportAttribute(Type t, string guid)
        : base(t)
    {
        PluginID = guid.ToUpper();
    }

    public string PluginID { get; set; }
}


[PluginExport(typeof(IAccountsPlugin),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class BillingModule : IAccountsPlugin, IPluginSettings
{
   // my class contents
}

或者我会做这样的事情更好......?

// or would i be better of by implementing a plugin base, and getting instances of the plugin via a secondary factory?
public interface IWellKnownPluginBase
{
    Guid PluginID { get; }
    Version Version { get; }
    IPluginSettings Settings { get; }
    Type GetPluginInterfaceType { get; }
    object PluginInterfaceFactory();
}

public interface IMyPlugin
{
    void DoSomethingCool();
}

[Export(typeof(IWellKnownPluginBase))] 
public class MyPluginWrapper : IWellKnownPluginBase
{
    private readonly string ID = "BE112EA1-1AA1-4B92-934A-9EA8B90D622C";

    Guid PluginID { get { return Guid.Parse(ID); } }
    Version Version { get {return new Version(1,0,0); } }
    IPluginSettings Settings { get { return new SomethingThatImplementsIPluginSettings(); }
    Type GetPluginInterfaceType { get { return gettype(IMyPlugin); }
    object PluginInterfaceFactory() { return new MyPlugin(); }

    class MyPlugin : IMyPlugin
    {
        void DoSomethingCool() {}
    }
}

问题4 - 可以重写PluginExport以使用构造函数中的接口列表注册多个接口吗?

[Export(typeof(IPluginSettings))]
[PluginExport(typeof(IAccountsPlugin),"BE112EA‌​1-1AA1-4B92-934A-9EA8B90D622C")]
public MyModule class : IModule, IPluginSettings
{
} 

1 个答案:

答案 0 :(得分:1)

  

在上面的场景中,我必须实例化该类以测试它是否实现了特定的接口,是否有更好的方法使用Metadata执行此操作并增强PluginExportAttribute以接受辅助接口类型列表?

通常你会通过多次出口来做到这一点:

[Export(typeof(IPluginSettings))]
[Export(typeof(IModule))]
public class MyModule : IModule, IPluginSettings
{
}

而不是检查接口是否存在,消费者(即导入者,或者在你的情况下是GetExports的调用者)可以只是要求正确的接口。