I've been studying Observer parttern since this morning, but can't seem to figure out how to implement it with the built-in interfaces. I already looked at some examples but couldn't find any simple example yet.
Here's my code so far, inspired by the Microsoft Documentation :
class ObservableClass : IObservable<bool>, IDisposable { public bool observableBool; public List<IObserver<bool>> observers; public ObservableClass() { this.observableBool = false; this.observers = new List<IObserver<bool>>(); } public IDisposable Subscribe(IObserver<bool> observer) { if (!observers.Contains(observer)) { AddObserver(observer); } return this; } public void Dispose() { Console.WriteLine("Disposing..."); } public void AddObserver(IObserver<bool> obs) { this.observers.Add(obs); } public void RemoveObserver(IObserver<bool> obs) { this.observers.Remove(obs); } public void SwapBool() { observableBool = !observableBool; } } the observable class contains an observableBool field. I want to notify the Observer when that field changes value.
Here's my Observer :
class ObserverClass : IObserver<bool> { public IDisposable observable; public void OnCompleted() { Console.WriteLine("Completed"); } public void OnError(Exception error) { Console.WriteLine("error"); } public void OnNext(bool value) { Console.WriteLine("Next"); } public virtual void Subscribe(IObservable<bool> obs) { if (obs != null) observable = obs.Subscribe(this); } public void stopObserve() { observable.Dispose(); } } And finally my Program :
static void Main(string[] args) { ObservableClass observable = new ObservableClass(); ObserverClass observer = new ObserverClass(); observer.Subscribe(observable); Console.WriteLine("subscribed observer"); observable.SwapBool(); Console.WriteLine("performed swapBool"); } Expected output :
subscribed observer Completed //Returned by ObserverClass.OnComplete() performed swapBool How to make this work ? How to call on OnComplete and the other methods of ObserverClass everytime observableBool changes ?
I know there are other ways to do that, but my goal is to be able to use IObserver and IObservable.
21 Answer
You iterate over your set of observables to notify them:
public void SwapBool() { observableBool = !observableBool; foreach (observable in observers) { observable.OnNext(observableBool); } } You are meant to call OnNext when there is a new value. OnComplete is used to notify that there will be no more values.
I just noticed your observable is IDisposable...
First of all, disposing the result of Subscribe should unsubscribe that observer. Not dispose the observable.
In fact, I would expect that disposing the observable means that it will no longer be sending values (calls OnComplete on everybody and releases the list of observers).
Other concerns include:
- You probably want a set type so you can add and remove observables more efficiently.
- List is not thread-safe.
- Why are you exposing your fields?