2011-02-09 2 views
6

값 비싸고 내 응용 프로그램 (Lucene.Net IndexReader)을 통해 사용할 수 있어야하는 threadsafe 객체가 있습니다.Lucene.Net 용 StructureMap '조건부 싱글 톤'.Net IndexReader

개체가 무효화 될 수 있습니다. 개체를 다시 만들어야 할 때 (IndexReader.IsCurrent가 false이고 IndexReader.Reopen을 사용하여 새 인스턴스가 필요함).

IoC 컨테이너 (StructureMap)를 사용하여 개체 생성을 관리하고 싶지만이 시나리오가 가능하면 해결할 수 없습니다. 그것은 일종의 "조건부 싱글 톤"수명주기처럼 느껴집니다.

StructureMap에서 이러한 기능을 제공합니까? 대체 제안 사항이 있습니까?

답변

3

아마도 PerRequest의 범위를 사용하고 IndexReader을 직접 반환하지 않을 것입니다. 대신, 클래스 수준에서 개최되는 정적 참조에 대한 검사를 수행하는 IndexReader의 추상화를 반환합니다.

shim/proxy/abstraction의 속성에 액세스 할 때 정적 참조를 확인한 다음 (물론 스레드로부터 안전하게 만들 수 있음) 다시 필요한 경우 IndexReader을 다시 가져옵니다. 사용자.

+0

. 인터페이스/외관 뒤에있는 인스턴스를 숨겨 오브젝트 풀링과 같은 전략을보다 쉽게 ​​구현할 수 있다고 생각하십시오. – Steven

+0

필자는 이것을 고려했지만 오브젝트 생성 및 수명 관리를위한 저장소를 IoC 컨테이너에서 제거하는 것은 수치 스럽습니다. 분명히 나를 위해 일하게 될 것이고, 더 많은 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 등록 :

내가 casperOne에 동의
For<IndexReaderProxy>().Singleton().Use(
      new IndexReaderProxy(FSDirectory.Open(new DirectoryInfo(LuceneIndexPath)), true) 
     ); 
+0

내용이 질문과 병합되어야합니다. – casperOne

+0

답변 인 경우 수락해야합니다. –

+0

첫 번째 if (_indexReader.IsCurrent()) return; 바깥 쪽에서는 Lucene.Net.Store.AlreadyClosedException을 throw 할 수 있습니다.이 예외는 catch해야합니다. 이 스레드가 잠금을 입력 할 수 있으면 IndexReader가 현재 색인에서 다시 열렸습니다. – ENOTTY