В итоге я выбрал простой прокси-объект, который оборачивает реальный IndexReader и управляет повторным открытием. Поскольку мне нужно использовать один и тот же экземпляр этого в запросах, я использую StructureMap, чтобы предоставить его единый экземпляр. Код ниже.
Я исследовал создание настраиваемого StructureMap ILifecycle, чтобы справиться с этой ситуацией, но далеко не ушел, см. этот вопрос .
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)
);