2011-02-09 21 views
6

Tôi có một đối tượng threadsafe đắt tiền để tạo và cần có sẵn thông qua ứng dụng của tôi (một Lucene.Net IndexReader).StructureMap 'singleton có điều kiện' cho Lucene.Net IndexReader

Đối tượng có thể trở thành không hợp lệ, tại thời điểm tôi cần tạo lại nó (IndexReader.IsCurrent là sai, cần một phiên bản mới bằng cách sử dụng IndexReader.Reopen).

Tôi muốn có thể sử dụng một thùng chứa IoC (StructureMap) để quản lý việc tạo đối tượng, nhưng tôi không thể làm việc nếu kịch bản này là có thể. Nó giống như một loại vòng đời "có điều kiện".

Bản đồ cấu trúc có cung cấp tính năng như vậy không? Bất kỳ đề xuất thay thế nào?

Trả lời

3

Tôi có thể sử dụng phạm vi PerRequest và không trả lại trực tiếp số IndexReader. Thay vào đó, tôi sẽ trả về một trừu tượng của các IndexReader mà sẽ thực hiện một kiểm tra trên một tham chiếu tĩnh được tổ chức trên cấp lớp. Sau đó, khi tài sản của bạn trên shim/proxy/abstraction được truy cập, nó sẽ kiểm tra tham chiếu tĩnh (bạn sẽ làm cho nó an toàn thread, tất nhiên) và lấy lại IndexReader nếu cần trước khi đưa nó trở lại người dùng.

+0

Tôi đồng ý với casperOne. Hãy suy nghĩ về ẩn dụ đằng sau một giao diện/mặt tiền để bạn có thể dễ dàng thực hiện các chiến lược như đối tượng tổng hợp. – Steven

+0

Tôi đã xem xét điều này, nhưng nó cảm thấy xấu hổ khi loại bỏ resposibiliy để tạo đối tượng và quản lý suốt đời khỏi container IoC. Nó chắc chắn sẽ làm việc cho tôi và sẽ là giải pháp của tôi trở lại mùa thu nếu tôi không đến với bất cứ điều gì hơn IoC trung tâm. –

1

Cuối cùng tôi đã đi cho một đối tượng proxy đơn giản kết thúc tốt đẹp IndexReader thực tế và quản lý Mở lại. Như tôi cần phải sử dụng cùng một ví dụ này qua yêu cầu tôi đang sử dụng StructureMap để cung cấp một ví dụ singleton của nó. Mã dưới đây.

Tôi đã điều tra việc tạo Sơ đồ trang web Sơ đồ cấu trúc tùy chỉnh để xử lý tình huống này, nhưng không đi xa, xem 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; 
     } 
    } 
} 

Và việc đăng ký StructureMap:

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

Nội dung có thể được hợp nhất với câu hỏi. – casperOne

+0

Nếu đây là câu trả lời, có lẽ nó nên được chấp nhận. –

+0

đầu tiên nếu (_indexReader.IsCurrent()) trả về; bên ngoài khóa có thể ném ra một Lucene.Net.Store.AlreadyClosedException, sẽ bị bắt. Khi chuỗi này có thể nhập khóa, chỉ số IndexReader đã được mở lại trên chỉ mục hiện tại. – ENOTTY

Các vấn đề liên quan