您好我有一个检测元数据属性的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),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public MyModule class : IModule, IPluginSettings
{
}
答案 0 :(得分:1)
在上面的场景中,我必须实例化该类以测试它是否实现了特定的接口,是否有更好的方法使用Metadata执行此操作并增强PluginExportAttribute以接受辅助接口类型列表?
通常你会通过多次出口来做到这一点:
[Export(typeof(IPluginSettings))]
[Export(typeof(IModule))]
public class MyModule : IModule, IPluginSettings
{
}
而不是检查接口是否存在,消费者(即导入者,或者在你的情况下是GetExports
的调用者)可以只是要求正确的接口。