StructureMap'条件单例'用于Lucene.Net IndexReader

时间:2011-02-09 17:53:49

标签: c# singleton structuremap ioc-container lucene.net

我有一个线程安全对象,创建起来很昂贵,需要通过我的应用程序(Lucene.Net IndexReader)提供。

对象可能变为无效,此时我需要重新创建它(IndexReader.IsCurrent为false,需要使用IndexReader.Reopen的新实例)。

我希望能够使用IoC容器(StructureMap)来管理对象的创建,但如果可能出现这种情况,我无法解决。感觉就像某种“有条件的单身”生命周期。

StructureMap是否提供这样的功能? 还有其他建议吗?

2 个答案:

答案 0 :(得分:3)

我可能会使用PerRequest范围而不直接返回IndexReader。相反,我将返回IndexReader的抽象,它将对类级别上的静态引用执行检查。

然后,当访问shim / proxy / abstraction上的属性时,它将检查静态引用(当然,你会使它成为线程安全的)并在交付之前重新获取IndexReader它回给用户。

答案 1 :(得分:1)

最后,我找到了一个简单的代理对象,它包装了实际的IndexReader并管理了重新打开。因为我需要跨请求使用相同的实例,所以我使用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;
        }
    }
}

结构地图注册:

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