Es ist wahrscheinlich eine Mischung aus einem MEF-Metadatenattribut und einer abstrakten Basisklasse.
public interface IPluginMetadata
{
Guid PluginId { get; }
}
public interface IPlugin : IPluginMetadata
{
void Initialise();
}
ich durchgesetzt habe, dass die IPlugin
Schnittstelle auch unseren Metadaten Vertrag IPluginMetadata
erben: Ich würde meinen Plugin Vertrag als so etwas wie definieren. Als nächstes können wir eine eigene Export-Attribut erstellen:
[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; }
}
Sie brauchen nicht um den Export-Attribut mit dem Metadaten-Vertrag IPluginMetadata
zu dekorieren, als MEF ohnehin die Eigenschaften projizieren wird, aber ich ziehe es so zu tun, also wenn Ich führe Änderungen in meinen Metadatenvertrag ein, dann sollte auch mein Exportattribut aktualisiert werden. Kein Schaden, kein Foul.
Sobald wir dies getan haben, können wir eine abstrakte Basisklasse, von der Definition unseres Plugin Vertrag zu implementieren:
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();
}
Wir können dann die Sitte durch die abstrakte Klasse Konstruktor Attribut greifen, und die Eigenschaft gelten entsprechend. Dass wir tun können:
public IPlugin GetPlugin(Guid id)
{
var plugin = container
.GetExports<IPlugin, IPluginMetadata>()
.Where(p => p.Metadata.PluginId == id)
.Select(p => p.Value)
.FirstOrDefault();
return plugin;
}
Und auch:
[ExportPlugin("BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class MyPlugin : PluginBase
{
public override Initialise()
{
Console.WriteLine(PluginId);
}
}
Wir können sehen, dass aus PluginId
ausgesetzt wird sowohl durch exportierten Metadaten sowie eine Eigenschaft unserer Plug-ins.
Dieser Code ist alles noch nicht getestet, aber ich hoffe, es bringt Sie in die richtige Richtung.
+1 hübsche nette Idee und Implementierung! –
Das ist, was ich dachte, ich müsste gehen, obwohl ich darauf hinweisen werde, dass Sie keine Guid als den Typ einer Eigenschaft auf dem Metadatenobjekt haben können. Kein * riesiger * Deal, ich benutze nur einen CodeContract, um es im ctor des Attributs zu erzwingen –