MEF

2010-12-29 4 views
2

と「System.Lazy.LazyThreadSafetyMode」私はこのように私のクラスに異なるアセンブリからの多くの部分をインポートする使用:輸入部品の後MEF

[ImportMany(typeof(IServiceProvider))] 
private IEnumerable<Lazy<IServiceProvider, IDictionary<string, object>>> ServiceProviders 
    { 
     get; 
     set; 
    } 

を、サービスプロバイダは、オンデマンドで作成されます。

private IServiceProvider GetServiceProvider(String name) 
{ 
    foreach (var serviceProvider in ServiceProviders) 
    { 
     String currentName = (String)serviceProvider.Metadata["Name"]; 
     if (currentName == name) 
      return serviceProvider.Value; // Many threads receive here and try to create new instance. 
    } 

    return null; 
} 

上記のコードでコメントしたように、多くのスレッドはlazy変数のvalue(まだ作成されていない場合は、その新しいインスタンスを作成します)を同時に取得しようとします。部品をインポートする際

// Something here... 
Dictionary<string, object> metadata = new Dictionary<string,object>(); 
metadata.Add("Name", "test"); 
Lazy<IServiceProvider, IDictionary<string, object>> serviceProvider = new Lazy<IServiceProvider, IDictionary<string, object>>(ServiceProviderValueFactory, metadata, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); 
// Now access to 'serviceProvider.Value' creates an instance (if not created yet) in a thread-safe manner. 

private IServiceProvider ServiceProviderValueFactory() 
{ 
    // Create and return a new instance of 'IServiceProvider'. 
} 

MEFオブジェクト作成の心配を取り、私ができますLazyコンストラクタを使用したい:これはのように

Lazy<T>は、thread-safe的にインスタンス(value)を作成できるようにするコンストラクタを持っていますスレッドセーフなvalue作成のために私はどのようにわからない。

答えて

2

CompositionContainerを作成する場合は、コンストラクタにisThreadSafe=trueを渡します。

スレッドセーフなコンテナで再構成するのは安全ではないため、変更するカタログ、またはCompositionBatch、または拡張メソッドを使用しないでください。

+0

は実際に私が追加/削除し、コンテナから変更されたプラグインを置き換えるために、 'DirectoryCatalog'を更新する必要があります:ExportServices

は、ハードとして符号化されます。これはスレッドセーフですか? – Xaqron

+0

@Xaqronはい、スレッドの安全性に反するでしょう。これがサーバーサイドアプリケーションの場合は、将来のすべての要求に使用される新しいカタログとコンテナを作成し、現在の要求を完了するために現在のコンテナを使用できるようにするのが最善の方法です。クライアントアプリケーションの場合は、おそらくカタログの更新を行う前にコンテナにアクセスする可能性のある他のスレッドで作業を一時停止する必要があります。 –

1

私はこれがあなたが変えることができると確信していません。 Lazy<T, M>の型は内部クラスExportServicesで初期化され、オーバーライドできません。 ExportProviderをサブクラス化した場合、Lazy<T, M>を返すターゲットGetExportsまたはGetExportsCoreは抽象または仮想ではないため、上書きすることはできません。

return new Lazy<T, M>(..., LazyThreadSafetyMode.PublicationOnly); 
+0

+1詳細はわかりませんでした。ソースは 'codeplex'で利用可能ですが、私のバージョンをフォークするつもりはありません。 'MEF'や' Lazy'のような新しいライブラリは、パラメータ化されたコンストラクタに問題があり、私に多くの問題を引き起こしました。 – Xaqron