我正在寻找使用MEF作为我正在构建的应用程序的插件系统.我希望每个组件都有一个标识符(GUID),我希望能够查找它.但是,在使用导出的零件时,此ID也很有用.
有没有一种方法可以让我的元数据属性包含ID以及导出部分的属性(或方法),而不是让开发人员填写两次或使用反射从属性中找到它?
它可能是MEF元数据属性和抽象基类的混合体.我会将我的插件合约定义为:
public interface IPluginMetadata
{
Guid PluginId { get; }
}
public interface IPlugin : IPluginMetadata
{
void Initialise();
}
Run Code Online (Sandbox Code Playgroud)
我强制说该IPlugin
接口也继承了我们的元数据契约IPluginMetadata
.接下来,我们可以创建自定义导出属性:
[AttributeUsage(AttributeTargets.Class, Inherit = true), MetadataAttribute]
public class ExportPluginAttribute : ExportAttribute, IPluginMetadata
{
public ExportPluginAttribute(string pluginId) : base(typeof(IPlugin))
{
if (string.IsNullOrEmpty(pluginId))
throw new ArgumentException("'pluginId' is required.", "pluginId");
PluginId = new Guid(pluginId);
}
public Guid PluginId { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
您不需要使用元数据协定来修饰导出属性IPluginMetadata
,因为MEF无论如何都会投影属性,但我更喜欢这样做,所以如果我确实对我的元数据合同进行了更改,那么我的导出属性也应该更新.没有伤害,没有犯规.
一旦我们完成了这个,我们就可以定义一个抽象基类来实现我们的插件契约:
public abstract class PluginBase : IPlugin
{
protected PluginBase()
{
var attr = GetType()
.GetCustomAttributes(typeof(ExportPluginAttribute), true)
.Cast<ExportPluginAttribute>()
.SingleOrDefault();
PluginId = (attr == null) ? Guid.Empty : attr.PluginId;
}
public virtual Guid PluginId { get; private set; }
public abstract void Initialise();
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以通过抽象类的构造函数获取自定义属性,并相应地应用该属性.我们可以这样做:
public IPlugin GetPlugin(Guid id)
{
var plugin = container
.GetExports<IPlugin, IPluginMetadata>()
.Where(p => p.Metadata.PluginId == id)
.Select(p => p.Value)
.FirstOrDefault();
return plugin;
}
Run Code Online (Sandbox Code Playgroud)
并且:
[ExportPlugin("BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class MyPlugin : PluginBase
{
public override Initialise()
{
Console.WriteLine(PluginId);
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到out PluginId
通过导出的元数据以及插件的属性公开.
该代码都是未经测试的,但我希望它能推动您朝着正确的方向发展.
归档时间: |
|
查看次数: |
1875 次 |
最近记录: |