3

MEF を使用して、複数のアセンブリからエクスポートされた型を構成しています。ImportMany派生クラスで指定されているように、依存関係がある基本クラスを使用しています。次のようになります。

ベース アセンブリ:

public abstract class BaseClass
{
    [ImportMany(typeof(IDependency)]
    public IEnumerable<IDependency> Dependencies { get; private set; }

    protected BaseClass()
    {
        var catalog = GetCatalog();
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    protected abstract ComposablePartCatalog GetCatalog();
}

アセンブリ A:

[Export(typeof(BaseClass))]
public class MyA : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyA1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyA2 : IDependency {}

アセンブリ B:

[Export(typeof(BaseClass))]
public class MyB : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyB1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyB2 : IDependency {}

次に、ベース アセンブリですべてを構成します。

static void Main(string[] args)
{
    DirectoryCatalog catalog = new DirectoryCatalog(path, "*.dll");
    var container = new CompositionContainer(catalog);
    IEnumerable<BaseClass> values = container.GetExportedValues<BaseClass>();

    // both BaseClass instances now have 4 Dependencies - from both Assemby A and Assembly B!
}

MyAMEF を使用して と の両方を構成するとMyB、両方のアセンブリからエクスポートされIDependencyた -ies がそれぞれに含まれるという問題が発生します。と同じMyAように、エクスポートDependencyA1とのみを含めたいと思います。DependencyA2MyB

これにはおそらく依存性注入コンテナーを使用する必要があることはわかっていますが、MEF で実行できることを望んでいましたか?

4

2 に答える 2

1

基本的に BaseClass を複数回構成するこのアプローチを使用して、MEF の周りで奇妙なダンスを行っています。これにより、最後に行われた構成に基づいて異なる結果が得られます。コードが現在書かれている方法は、Main で発生する構成が最後に ImportMany を設定する方法になります。これは、コンストラクターが BaseClass を呼び出した後に発生するためです。アリエルと同様に、同じオブジェクトで複数の合成を行うことはお勧めしません。

MEF でこのようなことをしなければならない場合は、いくつかの方法で動作する可能性があります。1) コンストラクターで 2 番目の構成を行わず、代わりにIPartImportsSatisfiedNotificationを使用します。OnImportsSatisifed で 2 回目の構成を行いますが、2 回目の構成時にこのメソッドの 2 回目の呼び出しに注意してください。2)Arielが提案したことを行い、ImportManyを使用せず、代わりにGetExportedValuesを実行して、そのフィールドを他のアセンブリレベルのカタログに設定します。アセンブリごとに 1 つの派生クラスしか持たないという大きな仮定をまだ行っていることに注意してください。そうしないと、オーバーラップが発生します。3) ImportMany を派生クラスに移動し、各派生型 (IADependency または IBDendency) ごとに一意の依存型をインポートできます。4) メタデータを使用して、特定の派生型のインポートをフィルター処理できます。

これらのいずれかが完璧かどうかはわかりませんが、オプションを選択する場合、#4 のいくつかのバリエーションを使用し、メタデータを使用してインポート間をフィルター処理する可能性があります。MEF はインポートの順序をどのように決定しますか? を参照してください。これはインポートを注文する方法を示していますが、インポートをフィルタリングするための同様のコード サンプルが存在します。

于 2012-08-26T19:59:50.287 に答える
1

別のコンポジションの鼻の下でコンポジションを行うのは非常に厄介です;)。

したがって、container.GetExportedValues を手動で呼び出して解決し、[ImportMany] をまとめて取り除くように、コンストラクターで自分でプロパティを設定します。そして、それは外部構成で操作されていません。

HTH アリエル

于 2012-08-26T13:12:49.727 に答える