嗨,我有一个检测元数据属性的 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),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public MyModule class : IModule, IPluginSettings
{
}