2009-07-31 7 views
2

簡単な背景:MEF:ロードパーツ異なる特性を持っている(プラグイン)

私のチームは、新しい追加するための拡張可能なモデルを提供するために、マイクロソフトのマネージド拡張フレームワーク(MEF)を使用することを決定しました"提供者"を私たちのシステムに追加します。

これにより、新しいサードパーティプロバイダを簡単にプラグインすることができます。

注:私は、MEFが使用して起動して走っていたことに感心しました。

私の質問:

これらのプロバイダは、は、一般的に、我々はプロバイダのデータストリームとプロパティにアクセスする必要があり、実行時にシステムにこれらのプロバイダをロードするときに異なる特性が、それらに関連付けられていますので。

プロパティが異なるために前記プロバイダプラグインを使用するにはどのようなアプローチが必要ですか?彼らはすべて同様の仕事をすることに注意してください。

マイソリューション:

一緒に働くための一貫したインターフェース/ プログラミングモデルが得られサードパーティプロバイダのそれぞれの周りに作成されている「ラッパー」で、その結果、プロバイダが準拠しなければならないインターフェースを作成します。各プロバイダ。

プラグイン=サードパーティのデータソース(プロバイダ)+一般的なインターフェイスの実装。

+ ve: 上記のプラグインには、より複雑なリフレクションベースの動的「プラグ」は必要ありません。

-ve: 各プロバイダのラッパーを記述する必要があります。

さらに注意(我々は関係なく、MEFのエクスポートタグを追加する必要があります):インターフェース/ラッパーアプローチは最も簡単になります私には

を私はリフレクションベースのアプローチを検討するよう指示されたかもしれリフレクションを利用して、実行時にシステムに公開されるプロパティを発見します。

私は他のどの解決策にも賛成ではありませんが、コミュニティの考えを聞くことに興味があります(ほとんどが私よりも経験が豊富です)。

ありがとうございました。

答えて

1

あなたは「プロパティ」と「データストリーム」が何を話しているのかはまだ分かりませんが、それでもなおあります。

はい、一般的なインターフェイスは常に良いことです。あなたはこれらすべての「プロパティ」を持っていると、そのようなので、私は次のことをお勧め:「ラッパー」の

interface IProperty 
{ 
    string Name { get; } 
    object Value { get; } 
} 

interface IDataStreamProvider 
{ 
    Stream OpenStream(); 
} 

interface IPlugin 
{ 
    ReadOnlyCollection<IProperty> Properties { get; } 

    ReadOnlyCollection<IDataStreamProvider> DataStreams { get; } 
} 

スピーキング:私はそれらの意図を理解していません。すべてのサードパーティ製のプラグインがIPluginインタフェースを実装する必要がありますし、この中のいずれかとしてExportAttributeまたはPluginAttributeで飾られている必要があります

class PluginAttribute : ExportAttribute 
{ 
    public PluginAttribute() : 
     base(typeof(IPlugin)) 
    { 
    } 
} 

反射があるため保守性の懸念のために可能な限り避けるべきです。

1

私がこのような情報を追加するために行ったことは、プラグインのカスタム属性を作成し、プラグインがロードされたときにMEFを使用してそれらを読み込むことです。名前、列挙型、int、その他の文字列のような属性クラスに何かを追加することができ、使い方は簡単です。しかし、注意してください、新しいプレビュー6は、それらがどのように扱われるかにいくつかの変更を加えました。あなたはその後、使用することができます

も、あなたが輸入に物事を追加する必要が
[MetadataAttribute] 
public class MyMetadataAttribute : Attribute 
{ 
    public MyType MyUsage { get; set; } 
} 

public interface IMyMetadataView 
{ 
    MyType MyUsage { get; } 
} 

public enum MyType 
{ 
    Undefined, 
    TypeOne, 
    TypeTwo 
} 

そしてプラグインで、あなたがこのようにそれを定義することができます...

[Export(typeof(IMyInterface))] 
[MyMetadataAttribute(MyUsage = MyType.TypeOne)] 
public class PluginClass: IMyInterface 
{ 
} 

[ImportMany(AllowRecomposition = true)] 
public IEnumerable<Lazy<IMyInterface, IMyMetadataView>> plugins { get; set; } 

各プラグインごとに直接データ

var typeOnePlugin = plugins.FirstOrDefault(p => p.Metadata.MyUsage == MyType.TypeOne); 

これも、7月にリリースされたプレビュー6を使用する方法です。

2

実際にはプレビュー6では、非公開のエクスポートがあり、メタデータを含むカスタムエクスポート属性を作成できるため、部分作成者が別のエクスポートを追加する必要はありません。すべてのインポート属性も開封済みです。

[MetadataAttribute] 
[AttributeUsage(AllowMultiple=false)] 
public class RuleAttribute : ExportAttribute { 
    public RuleAttribute(string name, string description) { 
    Name=name; 
    Description=description; 

    } : base(typeof(IRule)) 

    public string Name {get;private set;} 
    public string Description {get; private set;} 
} 

上記のRuleAttributeは、IRuleをエクスポートし、名前メタデータを提供することもできます。

使用量は、次のようになります。

[Rule("AddOneRule", "Adds one to the value")] 
public class AddOneRule { 
} 

HTH グレン

+0

マイナーまた、RuleAttributeクラスもでマークされるべきである。 [AttributeUsage(偽AllowMultiple =)] –

+0

更新、おかげでニック! StackOverflowのためのその機能が好きで、編集することができます;-) –

関連する問題