StructureMap 'условный синглтон' для Lucene.Net IndexReader - PullRequest
6 голосов
/ 09 февраля 2011

У меня есть потокобезопасный объект, который дорого создать и который должен быть доступен через мое приложение (Lucene.Net IndexReader).

Объект может стать недействительным, и в этот момент мне нужно создать его заново (IndexReader.IsCurrent имеет значение false, требуется новый экземпляр с использованием IndexReader.Reopen).

Я бы хотел использовать контейнер IoC (StructureMap) для управления созданием объекта, но я не могу понять, возможен ли этот сценарий. Это похоже на «условный одиночный» жизненный цикл.

Предоставляет ли StructureMap такую ​​функцию? Есть альтернативные предложения?

Ответы [ 2 ]

3 голосов
/ 09 февраля 2011

Я бы, вероятно, использовал бы область действия PerRequest и не возвращал бы IndexReader напрямую.Вместо этого я бы возвратил абстракцию IndexReader, которая выполняла бы проверку статической ссылки, хранящейся на уровне класса.

Затем, когда к вашему свойству в shim / proxy / abstraction обращаются, онпроверит статическую ссылку (вы, конечно, сделаете ее поточно-ориентированной) и при необходимости получите IndexReader, прежде чем вернуть его пользователю.

1 голос
/ 10 февраля 2011

В итоге я выбрал простой прокси-объект, который оборачивает реальный 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)
        );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...