Click here to Skip to main content
Click here to Skip to main content

Tagged as

IObserver and IObservable - A New addition to BCL

, 27 Sep 2010
Rate this:
Please Sign up or sign in to vote.
Here in the post, I am going to discuss about IObserver and IObservable interfaces and its connection to Push based approach on Reactive Framework.

Introduction

With the introduction of new interfaces, it is time to get it on with discussion. With the current release of VS 2010, there were two interfaces that were introduced viz, IObservable and IObserver. Here in the post, I am going to discuss about these interfaces and its connection to Push based approach on Reactive Framework.

IObserver and IObservable as a Dual to Enumerables

First, it should be noted, IObserver and IObservable are actually the mathematical dual of IEnumerable and IEnumerator. Based on iterator pattern, IEnumerable is actually a repository of elements that made up the objects. The IEnumerable holds all the objects and it uses IEnumerator to get each individual objects from the repository. The few methods in IEnumerator which the IEnumerable uses are MoveNext and Current. So for each iteration, the Enumerator calls MoveNext and assigns it to Current which is later on sent back to the external environment.

So if you consider the interface IEnumerable and IEnumerator, it looks like:

public interface IEnumerator<out T> : IDisposable
{
          T Current { get; }
          bool MoveNext();
          void Reset();
}
public interface IEnumerable<out T> : IEnumerable
{
     IEnumerator<T> GetEnumerator();
}

So the IEnumerator has MoveNext which is called every time when we need to yield next element from the store. The MoveNext sets the Current item and sends it back to the Environment. So IEnumerable might be considered as a Pull based approach and it is used for sequential retrieval of objects.

IObservable and IObserver introduced to BCL recently as stated are the mathematical dual of IEnumerable and IEnumerator. Let's see the interfaces a bit:

public interface IObserver<in T>
{
    void OnCompleted();
    void OnError(Exception error);
    void OnNext(T value);
}

and for IObservable, it is:

public interface IObservable<out T>
{
      IDisposable Subscribe(IObserver<T> observer);
}

Hence, if you see the difference between the two Interfaces, IEnumerator has Current and MoveNext. These methods are used to Pull objects from the repository. IObserver has OnNext which is used to Push objects to the repository. Again, if you look into IEnumerable, it uses GetEnumerator to pull back the object of IEnumerable, while IObservable has a Subscribe method which is used to push an Observer to the Observable. Hence you can easily say, Observable interfaces in BCL are a dual to Enumerables where the former uses Push based approach and the later uses pull based approach.

Where Are They Useful?

If you recollect the Observer design pattern, you should know it already. Observer pattern actually holds a list of dependent objects known as Observer and notifies when certain state of the Observer changes. We have already got an idea of ObservableCollection which notifies the change to the collection to the external environment. IObserver and IObservable gives you a chance to enhance this flexibility more. Let's see a few lines of code:

public class CustomObserver
{

    private ObservableCollection<int> myrepository;

    public ObservableCollection<int> MyRepository
    {
        get
        {
            this.myrepository = this.myrepository ?? new ObservableCollection<int>();
            return this.myrepository;
        }
    }

    public void LoadRepository(int item)
    {
        this.MyRepository.Add(item);
    }

    private List<int> filteredcollection;
    public List<int> FilteredCollection
    {
        get
        {
            this.filteredcollection = this.filteredcollection ?? new List<int>();
            return filteredcollection;
        }
    }
    public IDisposable GetObserved()
    {

        IObservable<IEvent<NotifyCollectionChangedEventArgs>> numberObserver = 
	Observable.FromEvent<NotifyCollectionChangedEventArgs>
	(this.MyRepository, "CollectionChanged");
        Action<IEvent<NotifyCollectionChangedEventArgs>> subscriptionAction = item =>
        {
            switch (item.EventArgs.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    var newValues = item.EventArgs.NewItems.Cast<int>().Where
							(n => n % 2 == 0);
                    this.FilteredCollection.AddRange(newValues);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (int n in item.EventArgs.OldItems)
                        this.FilteredCollection.Remove(n);
                    break;
                case NotifyCollectionChangedAction.Replace:
                    foreach (int n in item.EventArgs.OldItems)
                        this.FilteredCollection.Remove(n);
                    goto case NotifyCollectionChangedAction.Add;
            }
        };

        return numberObserver.Subscribe(subscriptionAction);
    }
}

So in this class, I have implemented a simple collection of objects and registered the PropertyChanged event of ObservableCollection. Hence the Action method SubscriptionAction will be called automatically and reevaluate the list FilteredCollection whenever the Observer MyRepository gets an object.

So to demonstrate, let's look at the Main method:

static void Main(string[] args)
{

    CustomObserver myobj = new CustomObserver();
    IDisposable unregisterobj = myobj.GetObserved();

    bool DoContinue = false;
    do
    {
        try
        {
            Console.Write("Enter a Value:");
            int item = Convert.ToInt32(Console.ReadLine());

            myobj.LoadRepository(item);

            Console.WriteLine("Filtered List counter : {0}", 
				myobj.FilteredCollection.Count);

            Console.WriteLine("Do you want to continue?[1/0]");
            DoContinue = Convert.ToInt32(Console.ReadLine()) == 1;
        }
        catch { continue; }
    } 
    while (DoContinue);

    Console.WriteLine("Disposing Registration...");
    unregisterobj.Dispose();

    Console.ReadKey();
}

Being so straightforward, we create an object of out class CustomObserver and called the method GetObserved which in turn calls Subscribe method from the Observer and returns the Disposable object. You must remember the Subscribe method returns a IDisposable which will be used to unsubscribe the method by just calling the Dispose method of it.

Just as you might expect, if you run the application, the application allows you to enter numeric values each of which is observed and added to the FilteredCollection. Hence when you enter Even values, the FilteredCollection gets updated.

The FromEvent is a method from Reactive framework that generates an Observable from an event. In the call, the Observer will observe the collection for the event CollectionChanged. We will discuss more about the Reactive framework later.

I hope you like my demonstration. Feel free to write your comments and feedback. Thank you for reading.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Abhishek Sur
Architect
India India
Did you like his post?
 
Oh, lets go a bit further to know him better.
Visit his Website : www.abhisheksur.com to know more about Abhishek.
 
Abhishek also authored a book on .NET 4.5 Features and recommends you to read it, you will learn a lot from it.
http://bit.ly/EXPERTCookBook
 
Basically he is from India, who loves to explore the .NET world. He loves to code and in his leisure you always find him talking about technical stuffs.
 
Presently he is working in WPF, a new foundation to UI development, but mostly he likes to work on architecture and business classes. ASP.NET is one of his strength as well.
Have any problem? Write to him in his Forum.
 
You can also mail him directly to abhi2434@yahoo.com
 
Want a Coder like him for your project?
Drop him a mail to contact@abhisheksur.com
 
Visit His Blog

Dotnet Tricks and Tips



Dont forget to vote or share your comments about his Writing
Follow on   Twitter   Google+

Comments and Discussions

 
AnswerOffsite PinmemberClifford Nelson5-Jun-13 8:42 
GeneralMy vote of 4 Pinmemberpriyank piyush6-Sep-10 23:24 
GeneralQuite confused PinmemberTiefeng You24-Aug-10 6:08 
GeneralRe: Quite confused PinmvpAbhishek Sur24-Aug-10 8:52 
GeneralRe: Quite confused PinmemberTiefeng You24-Aug-10 9:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 27 Sep 2010
Article Copyright 2010 by Abhishek Sur
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid