2010-11-21 9 views
4

私が構築しているアプリケーションのプラグインシステムにMEFを使用したいと考えています。各コンポーネントは、私が参照できるようにしたい識別子(GUID)を持っています。しかし、このIDは、エクスポートされた部分を扱う際に役立つものでもあります。MEFエクスポートされた部分のメタデータ

エクスポートされた部分にIDやプロパティ(またはメソッド)が含まれているメタデータ属性を持つことができる方法はありますか?開発者に2回記入したり、リフレクションを使用して属性?

答えて

7

MEFメタデータ属性と抽象基本クラスが混在している可能性があります。私はIPluginインターフェースはまた私達のメタデータ契約IPluginMetadataを継承することを強制しました

public interface IPluginMetadata 
{ 
    Guid PluginId { get; } 
} 

public interface IPlugin : IPluginMetadata 
{ 
    void Initialise(); 
} 

:私のようなものとしての私のプラグインの契約を定義します。 MEFはとにかくプロパティを投影しますが、私はそうすることを好む、そうかのように、メタデータ契約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; } 
} 

:次に、我々は、カスタムエクスポート属性を作成することができます私はメタデータコントラクトの変更を導入していますが、エクスポート属性も更新する必要があります。害はなく、ファウルはありません。

我々はこれをやったら、私たちはプラグインの契約を実装するから抽象基本クラスを定義することができます。

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が両方のエクスポートメタデータだけでなく、私たちのプラグインのプロパティを介して公開されることを見ることができます。

このコードはすべてテストされていませんが、正しい方向にあなたを押し込んでくれることを願っています。

+0

+1すてきなアイデアと実装! –

+1

これは、私が行くべきだと思っていたものですが、メタデータオブジェクトのプロパティの型としてGuidを持つことはできません。 *巨大な取引ではなく、CodeContractを使用して属性のctorで強制しています –

0

定数でGUIDを入れて、プロパティとメタデータの両方のためにそれを使用します。それはによって許可されていないとしてあなたは、stringの代わりにGuidタイプを使用することはできません

[Export(typeof(IFoo))] 
[ExportMetadata("GUID", _guid)] 
public class Foo : IFoo 
{ 
    private const string _guid = "abc"; 

    public string Guid { get { return _guid; } } 
} 

注意をconstキーワード。

関連する問題