2

簡単な背景:

私のチームは、システムに新しい「プロバイダー」を追加するための拡張可能なモデルを提供するために、Microsoft の Managed Extensibility Framework ( MEF ) を使用することにしました。

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

注: MEF を簡単に使用して起動して実行できることに感銘を受けました。

私の質問:

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

プロパティが異なるため、上記のプロバイダー プラグインを操作するには、どのようなアプローチを取る必要がありますか? それらはすべて同様の仕事をしていることに注意してください。

私の解決策:

プロバイダーが準拠する必要があるインターフェイスを作成します。これにより、各サードパーティ プロバイダーの周りに「ラッパー」が作成され、各プロバイダーと連携するための一貫したインターフェイス/プログラミング モデルが得られます。

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

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

-ve: プロバイダーごとにラッパーを作成する必要があります。(関係なく、MEF Export タグを追加する必要があります)

さらに注意:

私にとっては、インターフェイス/ラッパーのアプローチが最も単純ですが、システムに公開できるプロパティを実行時に発見するために、リフレクションを利用する可能性のあるリフレクション ベースのアプローチを調査するように言われました。

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

ありがとう。

4

3 に答える 3

2

実際、Preview 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 をエクスポートし、Name メタデータを提供することもできます。

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

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

HTH グレン

于 2009-08-04T05:32:22.577 に答える
1

あなたが話している「プロパティ」と「データストリーム」が何であるかはあまり明確ではありませんが、それでも.

はい、共通のインターフェースは常に良いことです。そして、これらすべての「プロパティ」などがあるので、次のことをお勧めします。

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

interface IDataStreamProvider
{
    Stream OpenStream();
}

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

    ReadOnlyCollection<IDataStreamProvider> DataStreams { get; }
}

「ラッパー」といえば、それらの意図がわかりません。すべてのサードパーティ プラグインはインターフェイスを実装する必要があり、次のようにまたはIPluginで装飾する必要があります。ExportAttributePluginAttribute

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

保守性の問題から、リフレクションはできるだけ避ける必要があります。

于 2009-07-31T14:26:13.663 に答える
1

このような情報を追加するために私が行ったことは、プラグインのカスタム属性をいくつか作成し、プラグインがロードされたときに MEF でそれらを読み取ることです。名前、列挙型、int、その他の文字列など、属性クラスに何でも追加でき、非常に使いやすいです。ただし、注意してください。新しい preview6 では、それらの処理方法がいくつか変更されています。

[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の使い方です。

于 2009-07-31T14:31:43.543 に答える