我正在尋找使用MEF插件系統爲我正在建設的應用程序。我希望每個組件都有一個(GUID)標識符,我希望能夠查找它們。但是,使用導出部分時,此ID也是非常有用的。MEF元數據從出口部分
有沒有一種方法,我可以有一個元數據屬性,其中包含ID以及導出的部分上的屬性(或方法),缺少開發人員填充兩次或使用反射從屬性中找到它?
我正在尋找使用MEF插件系統爲我正在建設的應用程序。我希望每個組件都有一個(GUID)標識符,我希望能夠查找它們。但是,使用導出部分時,此ID也是非常有用的。MEF元數據從出口部分
有沒有一種方法,我可以有一個元數據屬性,其中包含ID以及導出的部分上的屬性(或方法),缺少開發人員填充兩次或使用反射從屬性中找到它?
它很可能是MEF元數據屬性和抽象基類的混合。我會定義我的插件合同是這樣的:
public interface IPluginMetadata
{
Guid PluginId { get; }
}
public interface IPlugin : IPluginMetadata
{
void Initialise();
}
我已經執行了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; }
}
你並不需要裝飾合同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();
}
然後,我們可以獲取自定義的通過抽象類的構造屬性,並申請財產因此。我們可以這樣做:
public IPlugin GetPlugin(Guid id)
{
var plugin = container
.GetExports<IPlugin, IPluginMetadata>()
.Where(p => p.Metadata.PluginId == id)
.Select(p => p.Value)
.FirstOrDefault();
return plugin;
}
而且也:
[ExportPlugin("BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class MyPlugin : PluginBase
{
public override Initialise()
{
Console.WriteLine(PluginId);
}
}
我們可以看到,出PluginId
暴露既通過導出的元數據,以及我們的插件的屬性。
這段代碼都沒有經過測試,但我希望它能將您推向正確的方向。
把GUID在一個常數,並使用它既有財產和元數據:
[Export(typeof(IFoo))]
[ExportMetadata("GUID", _guid)]
public class Foo : IFoo
{
private const string _guid = "abc";
public string Guid { get { return _guid; } }
}
請注意,您不能使用Guid
類型,而不是string
,因爲這是不被許可const
關鍵字。
+1非常漂亮的想法和實施! – 2010-11-21 12:23:34
這就是我一直在想我必須去的地方,儘管我會指出你不能把Guid作爲元數據對象的屬性類型。不是一個巨大的交易,我只是使用CodeContract在屬性的ctor中執行它 – 2010-11-22 22:24:02