0

嗨,我有一个检测元数据属性的 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)在上述场景中,我必须实例化该类以测试它是否实现了特定接口,是否有更好的方法使用元数据执行此操作并增强 PluginExportAttribute 以接受辅助接口类型列表?

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

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

4)感谢一个提议的答案,我正在使用按照下面问题 4 snipit 构造的代码,它可以工作!出于好奇,是否有将多个单独的导出属性合并到 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
{
} 
4

1 回答 1

1

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

通常,您可以通过多个导出来做到这一点:

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

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

于 2012-05-22T14:23:35.950 回答