Interfejsy IObservable oraz IObserver

W przyszłych postach chcę zająć się Reactive Extensions, jednak zanim zacznę cykl postów o tym, najpierw przedstawię dwa interfejsy wprowadzone w .NET 4.0. Interfejsy umożliwiają implementację wzorca obserwator. IObserver powinien zostać zaimplementowany dla klasy, która chcę być powiadamiana o zmianach dokonywanych na klasie implementującej IObservable. Przyjrzyjmy się najpierw metodom IObserver:

  1. OnCompleted – obserwacja wszelkich zmian zakończona.
  2. OnError – wystąpił błąd.
  3. OnNext – Nowa zmiana np. dodano element do kolekcji.

Z kolei IObservable wymaga wyłącznie jednej metody, Subscribe odpowiedzialnej za subskrypcję obserwatora. Napiszmy więc klasę dokonującą zmian na bazie danych:

class PersonRepository:IObservable<string>
{        
        #region IObservable<string> Members

        private List<IObserver<string>> _observers = new List<IObserver<string>>();

        public IDisposable Subscribe(IObserver<string> observer)
        {
            _observers.Add(observer);
            return null;
        }       

        #endregion

        public void AddPerson(string person)
        {
            // jakas akcja
            if(person==null)
                _observers.ForEach(o => o.OnError(new NullReferenceException()));
            else
                _observers.ForEach(o=>o.OnNext(person));
        }
        public void Close()
        {
            _observers.ForEach(o => o.OnCompleted());
        }
}

Jak widać IObservable jest generycznym typem. W poście używam po prostu typu string. Metoda Subscribe odpowiedzialna jest za subskrypcję obserwatorów. Warto uwagę zwrócić na IDisposable. Dzięki temu można zaimplementować zwalnianie zasobów gdy obserwator jest już nie dostępny (pomięto to w poście). Następnie dodano dwie metody AddPerson oraz Close – tylko po to aby pokazać co można zrobić na podstawie IObservable. Gdy użytkownik wykona metodę AddPerson, wszyscy obserwatorzy zostaną o tym powiadomieni. Przejdźmy więc do implementacji IObserver:

class SampleObserver:IObserver<string>
{
        #region IObserver<string> Members

        public void OnCompleted()
        {
            MessageBox.Show("Completed");
        }

        public void OnError(Exception error)
        {
            MessageBox.Show(string.Format("Error: {0}", error.Message));
        }

        public void OnNext(string value)
        {
            MessageBox.Show(string.Format("Next: {0}",value));
        }

        #endregion
}

A na zakończenie przykład wykorzystania powyższych klas

PersonRepository repository=new PersonRepository();
repository.Subscribe(new SampleObserver());            
repository.AddPerson("test");
repository.AddPerson(null);
repository.Close();

Wykonanie AddPerson lub Close spowoduje wyświetlenie MessageBox, zgodnie z tym co zostało zaimplementowane w przykładowym obserwatorze. .NET dostarcza wyłącznie interfejsy, co może wydawać się nieco niepotrzebne. Zdecydowałem się jednak na takie wprowadzanie, aby następny post (o RX) był łatwiejszy w przyswojeniu.

2 thoughts on “Interfejsy IObservable oraz IObserver”

  1. Fajny post ale….
    NET dostarcza wyłącznie interfejsy, co może wydawać się nieco niepotrzebne.

    Ale jest to raczej niezbędne do IoC

Leave a Reply

Your email address will not be published.