2010-11-13 36 views
5

Thông thường khi bạn đăng ký thay đổi giá trị, bạn cũng muốn biết giá trị ban đầu. Tôi muốn IObservable của tôi để cache giá trị mới nhất (hoặc ban đầu) và đẩy giá trị đó vào đăng ký.Làm cách nào để nhận được IObservable để đẩy giá trị mới nhất khi đăng ký

Khi sử dụng các sự kiện đơn giản tôi thường kết thúc với mã mà trông giống như

x.SomeEvent += SomeEventHandler; 
SomeEventHandler(x, EventArgs.Empty); 

Sử dụng IObservable Tôi đã hy vọng để quấn sự kiện này với một cái gì đó đẩy giá trị ban đầu. Nếu tôi có nhiều thuê bao mà họ sẽ nhận được giá trị mới nhất khi thuê bao Tôi có một số mã mà làm việc ngay nếu tôi đăng ký ngay sau khi tạo IObservable nhưng không nếu sự kiện cháy trước khi đăng ký:

class Program 
{ 
    static void Main() 
    { 
     var s = new Source { Value = 1 }; 
     var values = Observable.Return(s.Value).Concat(
      Observable.FromEvent(
       h => s.ValueChanged += h, 
       h => s.ValueChanged -= h) 
      .Select(_ => s.Value)); 
     using (values.Subscribe(Console.WriteLine)) 
     { 
      s.Value = 2; // prints 1,2 as expected 
     } 
     using (values.Subscribe(Console.WriteLine)) 
     { 
      s.Value = 3; // prints 1,3 - expected 2,3 
     } 
    } 
} 

class Source 
{ 
    private int _value; 
    public int Value 
    { 
     get { return _value; } 
     set 
     { 
      if (_value == value) 
       return; 
      _value = value; 
      if (ValueChanged != null) 
       ValueChanged(this, EventArgs.Empty); 
     } 
    } 

    public event EventHandler ValueChanged; 
} 

Làm thế nào để tạo ra một IObservable hoạt động như mong đợi?

+0

'.Chọn (_ => s.Value) '- điều này rất kỳ lạ và có thể phá vỡ mọi thứ. Bạn không thể thay đổi sự kiện 'ValueChanged' để sự kiện arg có chứa giá trị mới không? – dtb

+0

Tôi không viết mã mà tôi đang nghe. Nếu tôi là tôi sẽ chỉ phơi bày một IObservable thay vì :) –

Trả lời

6

Giải pháp là đăng ký BehaviorSubject cho người quan sát và đăng ký tất cả người quan sát với BehaviorSubject. BehaviorSubject sẽ ghi nhớ thông báo cuối cùng và thông báo cho người quan sát mới về thông báo khi đăng ký.

Hãy xem phương thức mở rộng Observable.Publish có tham số initialValue. Điều này tạo ra một IConnectableObservable mà nội bộ sử dụng một BehaviorSubject.

var s = new Source { Value = 1 }; 

var values = Observable.FromEvent(h => s.ValueChanged += h, 
            h => s.ValueChanged -= h) 
         .Select(e => e.NewValue) 
         .Publish(s.Value); 

using (values.Connect())       // subscribes subject to event 
{ 
    using (values.Subscribe(Console.WriteLine)) // subscribes to subject 
    { 
     s.Value = 2; 
    }           // unsubscribes from subject 

    using (values.Subscribe(Console.WriteLine)) // subscribes to subject 
    { 
     s.Value = 3; 
    }           // unsubscribes from subject 

}           // unsubscribes subject from event 

(chưa được kiểm tra)

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