2016-12-03 30 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 –