【问题标题】:StructureMap 'conditional singleton' for Lucene.Net IndexReaderLucene.Net IndexReader 的 StructureMap '条件单例'
【发布时间】:2011-06-24 07:55:10
【问题描述】:

我有一个线程安全对象,它的创建成本很高,需要通过我的应用程序(Lucene.Net IndexReader)提供。

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

我希望能够使用 IoC 容器 (StructureMap) 来管理对象的创建,但我无法确定这种情况是否可行。感觉就像某种“有条件的单例”生命周期。

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

【问题讨论】:

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


    【解决方案1】:

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

    然后,当您在 shim/proxy/abstraction 上的属性被访问时,它会检查静态引用(当然,您会使其成为线程安全的)并在返回之前重新获取 IndexReader(如果需要)给用户。

    【讨论】:

    • 我同意 casperOne。考虑将实例隐藏在接口/外观后面,这样您就可以更轻松地实现对象池等策略。
    • 我考虑过这一点,但是将对象创建和生命周期管理的职责从 IoC 容器中移除是一种耻辱。如果我没有想出更多以 IoC 为中心的东西,它肯定对我有用,并且将成为我的后备解决方案。
    【解决方案2】:

    最后,我选择了一个简单的代理对象,它封装了实际的 IndexReader 并管理重新打开。由于我需要跨请求使用相同的 this 实例,因此我使用 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)
            );
    

    【讨论】:

    • 内容可能应该与问题合并。
    • 第一个if(_indexReader.IsCurrent())返回;锁之外可能会抛出一个 Lucene.Net.Store.AlreadyClosedException,应该被捕获。当这个线程可以进入锁时,IndexReader已经在当前索引上再次打开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多