2016-12-03 66 views
0

我有事件清單要做。所以我將訂閱者添加到訂閱列表中。在用戶完成其工作後,它必須退訂。用戶何時結束還不得而知。只有訂戶自己知道這一點。如何取消訂閱其中的用戶自我

什麼是最好的設計模式或解決方案。

我用觀察者模式

這是我的可觀察:

internal class EventProvider : IObservable<double> 
{ 
    private readonly List<IObserver<double>> _observers = new List<IObserver<double>>(); 

    public IDisposable Subscribe(IObserver<double> observer) 
    { 
     // check if observer exist... 
     _observers.Add(observer); 
     return new Unsubscriber<double>(_observers, observer); 
    } 

    public void OnTimingsRecieved(double timing) // some other event fires this 
    { 
     foreach (var observer in _observers) 
     { 
      observer.OnNext(timing); 
     } 
    }   

    //... 
} 

這是觀察:(可以有0到許多觀察者)

internal class EventObserver : IObserver<double> 
{ 
    private IDisposable _unsubscriber; 
    private readonly IReadOnlyList<Event> _events; 

    public EventObserver(IReadOnlyList<Event> events) 
    { 
     _events = events; 
    } 

    public void Subscribe(EventProvider provider) 
    { 
     _unsubscriber = provider.Subscribe(this); 
    } 

    private int _ind; 
    public void OnNext(double timings) 
    { 
     // may move to next event or not. it depends. 
     // _ind++; may execute or not 

     if (_ind == _events.Count) OnCompleted(); // time to unsubscribe it self 
    } 

    public void OnCompleted() 
    { 
     _unsubscriber.Dispose(); 
    } 

    //... 
} 

這是如通常那樣實現的Unsubscirber 。

internal class Unsubscriber<T> : IDisposable 
{ 
    private readonly List<IObserver<T>> _observers; 
    private readonly IObserver<T> _observer; 

    internal Unsubscriber(List<IObserver<T>> observers, IObserver<T> observer) 
    { 
     _observers = observers; 
     _observer = observer; 
    } 

    public void Dispose() 
    { 
     if (_observers.Contains(_observer)) 
      _observers.Remove(_observer); 
    } 
} 

當我嘗試在OnNext事件內部處理觀察者時出現問題。因爲我在foreach循環中修改了集合,所以我從列表中刪除了元素。

你將如何處理你想取消訂閱訂閱者的情況?有沒有更好的設計模式?


我欣賞看到不同的方法,而不是使用observable和observer。

假設你有這個事件。

public event EventHandler<double> TimeDiff; 

而且您有許多訂閱者的實例附加到TimerDiff並且能夠自行取消訂閱。

public class Reciever 
{ 
    Jobs listOfJobsToDo; 

    public void TimeDiffRecieved(double diff) 
    { 
     listOfJobsToDo.DoJob(diff); 
     if(somecondition) 
      Unsubscribe(); 
    } 
} 
+1

你爲什麼要實現自己的可觀察性?這充滿了危險。你應該使用內置的Rx實現。 – Enigmativity

+1

我明白了。我要刪除這個觀察者,並嘗試Rx,看看它是如何工作的,謝謝你的時間。 @Enigmativity –

回答

0

由於foreach不能處理我用於循環的集合更改。

在這種情況下,我們知道當觀察者工作時它可以自行處置。其他人不受影響。

這是對提供者的更正。

public void OnTimingsRecieved(double timing) 
{ 
    for (int i = 0; i < _observers.Count; i++) 
    { 
     var count = _observers.Count; // save count in case it may change. 
     var observer = _observers[i]; 
     observer.OnNext(timing);  // it may only dispose it self. 
     i -= count - _observers.Count; // decrement if observer unsubscribed. 
    } 
} 
+1

如果您使用此模式,可以更好地重用該解決方案(名爲Rx(Reactive)擴展)。 – Evk

+0

看起來很有趣。對我來說這完全是新事物。不好尋找。謝謝btw。 @Evk –