2011-02-09 9 views
6

私は作成するのに高価で、私のアプリケーション(Lucene.Net IndexReader)で利用可能なスレッドセーフなオブジェクトを持っています。Lucene.NetのためのStructureMap '条件付きシングルトン' .Net IndexReader

オブジェクトが無効になることがあります。その時点で、再作成する必要があります(IndexReader.IsCurrentはfalse、IndexReader.Reopenを使用して新しいインスタンスが必要です)。

IoCコンテナ(StructureMap)を使用してオブジェクトの作成を管理したいと考えていますが、このシナリオが可能な場合はうまくいかない場合があります。何らかの「条件付きシングルトン」ライフサイクルのように感じます。

StructureMapはこのような機能を提供しますか? 代替候補がありますか?

答えて

3

おそらくPerRequestの範囲を使用し、IndexReaderを直接返さないでしょう。代わりに、私はIndexReaderの抽象概念を返し、クラスレベルで保持されている静的参照のチェックを行います。

次に、shim/proxy/abstractionのプロパティにアクセスすると、静的な参照がチェックされます(スレッドセーフであることを確認します)。IndexReaderを再度取得してから戻します。ユーザー。

+0

私はcasperOneに同意します。インターフェイス/ファサードの背後にあるインスタンスを隠すことで、オブジェクトプーリングなどの戦略をより簡単に実装できるようになります。 – Steven

+0

私はこれを考慮しましたが、IoCコンテナからオブジェクトの作成と生涯管理のためにresposibiliyを削除することは残念です。間違いなくIoC中心のものを考え出すことができなければ、間違いなく私にとってはうまくいくでしょう。 –

1

最後に、私は実際のIndexReaderをラップし、Reopeningを管理する単純なプロキシオブジェクトに行きました。私はこの要求の横に同じインスタンスを使用する必要があるので、私はそれのシングルトンインスタンスを提供するためにStructureMapを使用しています。以下のコード。

この状況を処理するためにカスタムのStructureMap ILifecycleを作成することを検討しましたが、それほど遠かったわけではありません。this questionを参照してください。

public class IndexReaderProxy 
{ 
    private IndexReader _indexReader; 
    private readonly object _indexReaderLock = new object(); 

    public IndexReaderProxy(Directory directory, bool readOnly) 
    { 
     _indexReader = IndexReader.Open(directory, readOnly); 
    } 

    public IndexReader GetCurrentIndexReader() 
    { 
     ReopenIndexReaderIfNotCurrent(); 
     return _indexReader; 
    } 

    private void ReopenIndexReaderIfNotCurrent() 
    { 
     if (_indexReader.IsCurrent()) return; 
     lock (_indexReaderLock) 
     { 
      if (_indexReader.IsCurrent()) return; 
      var newIndexReader = _indexReader.Reopen(); 
      _indexReader.Close(); 
      _indexReader = newIndexReader; 
     } 
    } 
} 

とのStructureMap登録:

For<IndexReaderProxy>().Singleton().Use(
      new IndexReaderProxy(FSDirectory.Open(new DirectoryInfo(LuceneIndexPath)), true) 
     ); 
+0

コンテンツはおそらく質問にマージされるべきです。 – casperOne

+0

これが答えの場合は、おそらく受け入れられるはずです。 –

+0

最初の if(_indexReader.IsCurrent())return; ロックの外側には、Lucene.Net.Store.AlreadyClosedExceptionがスローされる可能性があります。 このスレッドがロックに入ることができるとき、IndexReaderは現在のインデックスで再び開かれました。 – ENOTTY

関連する問題