2012-03-29 7 views
9

MEFを使用してコンストラクタパラメータの注入に関する質問がたくさんあることがわかりましたが、私の場合は少し異なります。MEF:CreationPolicy.NonSharedを使用しているときに、異なるコンストラクタパラメータを渡す

PartCreationPolicy(CreationPolicy.NonShared)GetExportedValueの組み合わせを使用しているときに、異なるパラメータ値を部品のコンストラクタに渡す方法があることを知りたいと思いますか?

例:上記の例で

[PartCreationPolicy(CreationPolicy.NonShared)] 
[Export] 
public partial class Foo 
{ 
    [ImportingConstructor] 
    public Foo([Import("SomeParam")]object parameter) 
    { 
     ... 
    } 
} 

とどこか...

container.ComposeExportedValue("SomeParam", "Some value..."); 
var instance = container.GetExportedValue<Foo>(); 

、私はそれが二度目はChangeRejectedExceptionの原因となります実行しているように、一度だけComposeExportedValueを使用することができます。

だから、私の質問は以下のとおりです。

  1. それぞれの新しいインスタンスのために、上記のシナリオでSomeParamの値を変更するための他の方法はありますか?
  2. そうでない場合は、他のDIフレームワークを使用せずにこれを達成できる他の方法は何ですか? 1つ目のことは、System.Collections.Concurrent.ConcurrentQueueのようなものを公開するサービスを作成し、GetExportedValueを呼び出す前にパラメータ値をエンキューしてから、その部分のコンストラクタの値をデキューすることです。しかし、これはハックであり、解決するよりも多くの問題を作り出します。
  3. 上記の質問に対する答えが「いいえ」の場合、MEFと他のDI/IOCフレームワークの組み合わせでこれを達成する他の方法はありますか?

ありがとうございました。 :)
よろしく、
ヨーゲッシュJagota

答えて

2

上記の質問の両方への答えがノーであれば、MEFの組み合わせや他のいくつかのDI/IOCフレームワークでこれを達成するために他の方法がありますか?

私は質問1と2の答えは実際にはないと思います。

私はAutoFacを試してみると、きめ細かい制御が得られ、integrates with MEFです。

builder.Register(c => new Bar(new Foo(param)); 
builder.Register(c => new Baz(new Foo(param2)); 
+0

の下に表示リポジトリのように、最初の段階で私がAutoFac/MEFの統合で探していますが、 'RegisterComposablePartCatalog'を使用した場合どのように私は登録を扱うことができますか? AutoFacによって自動的に行われるので、私はここで 'Register'を使うことはできません。 AutoFacに '[ImportingConstructor]'を使わずに、私が提供するパラメータを持つデフォルト以外のコンストラクタを使って特定のエクスポートをインスタンス化する必要があることをどのように伝えることができますか? – Yogesh

+0

@Yogesh:(あなたがプラグインの動的検出が必要な場合)あなたは、いくつかのコンポーネントは、(あなたがきめの細かい制御が必要な場合)AutoFacに登録して、MEFでエクスポート他のことができます。しかし、同じコンポーネントに対して両方を混在させることはできません。もう一つの選択肢は、AutoFacに完全に切り替えることです。 [Scanning](http://code.google.com/p/autofac/wiki/Scanning)を使用して、必要に応じてMEFのような動的探索を行うことができます。実際に働いたのは –

+0

です。これを行う方法は、新しい登録を既存のコンテナに追加することを可能にする 'IContainer'の' Update'メソッドを使用することです。ありがとう。 :) – Yogesh

1

あなたには、いくつかのロジックに応じて、同じインターフェイスの異なるインスタンスを使用したい場合(適用されます。たとえば、それはBarBazインスタンスが異なるパラメータで自分Fooインスタンスを取得するようにしますが、このような登録を設定することができます戦略パターン)をMEFの1つの方法で使用してExportMetadata属性を使用します。たとえば あなたはIDbManagerを持っていて、それの2つの実装を持っている場合は1 OracleとのSQLを言うならば、 1.メタデータ

public interface IDbManagerMetadata 
{ 
    DataProvider DataProvider { get; } 
} 

2を保持するメタデータ・インタフェースを作成します。属性クラスを作成し、以下のよう

[MetadataAttribute] 
public class DbManagerMetadataAttribute : Attribute, IDbManagerMetadata 
{ 
    public DataProvider DataProvider { get; set; } 
} 
  1. 戦略例

    パブリック列挙型データプロバイダ { オラクル、 SQL、 } [InheritedExport] パブリックインターフェースIDbManager { ボイド初期化(); }

    [InheritedExport(typeof演算(IDbManager))] パブリッククラスDBManagerの:IDbManager {公共DBManagerの(データプロバイダproviderType) {_providerType = providerType。 }

    public void Initialize() 
    { 
        Console.WriteLine("provider : {0}", _providerType); 
    } 
    
    public DataProvider _providerType { get; set; } 
    

    }

2つの異なる実装

[Export(typeof(IDbManager))] 
[DbManagerMetadata(DataProvider = DataProvider.Oracle)] 
public sealed class OracleDataProvider : DbManager 
{ 
    public OracleDataProvider():base(DataProvider.Oracle) 
    { 

    } 
} 

そして

[Export(typeof(IDbManager))] 
[DbManagerMetadata(DataProvider = DataProvider.Sql)] 
public sealed class SqlDataProvider : DbManager 
{ 
    public SqlDataProvider() 
     : base(DataProvider.Sql) 
    { 
    } 
} 

そして、あなたは私たちが作成したメタデータ・インタフェースを使用して使用するかを決めることができます

[Export] 
public class Repository 
{ 
    private IDbManager _dbManager; 

    private readonly IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> DbManagers; 

    [ImportingConstructor] 
    public Repository([ImportMany(typeof(IDbManager))]IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> dbManagers) 
    { 
     this.DbManagers = dbManagers; 
     var _dbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value; 
    } 

    public void Execute() 
    { 
     var oracleDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value; 

     oracleDbManager.Initialize(); 

     var sqlDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Sql).Value; 

     sqlDbManager.Initialize(); 
    } 
} 
関連する問題