You know you are a techie at heart if you find yourself getting excited at the introduction of a couple of new interfaces.

.NET 4.0 introduces IObservable (Publisher) and IObserver (Subscriber). These interfaces were long overdue – for a couple of reasons:

  1. The ubiquitous nature of the Publish Subscribe pattern.
  2. The cludgeability of implementing these using events and delegates. Prior to these, one could implement the pattern using events and delegates. This came with its own set of gotchas.
  3. Even a WCF Publish Subscribe  implementation could not get away from explicitly publishing ( using events ) and subscribing ( using event handlers)

And while these new interfaces will not save you the effort of an actual implementation, they provide a standard template for implementing the publish subscribe pattern in .NET. This article provides:

  1. A simple, starting implementation of these two interfaces.
  2. As a second step, to illustrate a real-world usage of the sample implementation, a MagazinePublisher class is defined. This class maintains a list of all magazine subscribers – and notifies them whenever a new issue is available.

This sample application (full source code available below) can be used as a starting point for any publish subscribe application.

The ‘Publisher’ Interface

  1. In these new interfaces, the Publisher goes by the name Observable.
  2. Two primary responsibilities of the Publisher are:
    • a) Subscription and Unsubscription (Adding and Removing subscribers)
    • b) Notification (of all subscribers)

 

Subscription and Unsubscription

The implementation of IObservable(T) contains a subscribe method – which returns an instance of the RemoveMe class (which implements the IDisposable interface). This ensures that subscribers can call Dispose() when they are ready to unsubscribe.

Code Snippet
  1. public IDisposable Subscribe(IObserver<T> observer)
  2.         {
  3.             if (!observers.Contains(observer))
  4.             {
  5.                 observers.Add(observer);
  6.             }
  7.  
  8.             return new RemoveMe(observers, observer);
  9.         }
  10.  
  11.         private class RemoveMe : IDisposable
  12.         {
  13.             private List<IObserver<T>> observers;
  14.             private IObserver<T> observer;
  15.  
  16.             public RemoveMe(List<IObserver<T>> observers, IObserver<T> observer)
  17.             {
  18.                 this.observers = observers;
  19.                 this.observer = observer;
  20.             }
  21.  
  22.             public void Dispose()
  23.             {
  24.                 if (observer != null && observers.Contains(observer))
  25.                 {
  26.                     observers.Remove(observer);
  27.                 }
  28.             }
  29.         }

 

Notification

Notify can be called to notify all observers that there are changes in the observed object.

Code Snippet
  1. protected void Notify(T obj)
  2.       {
  3.           foreach (IObserver<T> observer in observers)
  4.           {
  5.               observer.OnNext(obj);
  6.           }
  7.       }

 

The Subscriber

Now that we have successfully described the two main responsibilities of the Publisher, we are ready to look at a sample Subscriber. The only thing a Subscriber needs to do is implement the IObserver<T> interface – using the Publisher as the type T that it is observing. This is a particular simple approach – even though it somewhat couples the subscriber to a specific publisher type.

Since the Publisher instance is passed in to the OnNext method, it is easy to retrieve all Publisher specific info in the subscriber. This example shows a subscriber getting notified of a new issue – and printing out the month of the issue.

Code Snippet
  1. /// <summary>
  2.     /// ‘Real-World’ Subscriber – Notice that it takes the type parameter MagazinePublisher in the IObserver interface
  3.     /// </summary>
  4.     class Subscriber : IObserver<MagazinePublisher>
  5.     {
  6.         public void OnCompleted()
  7.         {
  8.             Console.WriteLine(“Unsubscribed”);
  9.         }
  10.  
  11.         public void OnError(Exception error)
  12.         {
  13.             Console.WriteLine(“Error”);
  14.         }
  15.  
  16.         public void OnNext(MagazinePublisher mp)
  17.         {
  18.             Console.WriteLine(“New Issue: “ + mp.NewIssue);
  19.         }
  20.     }

 

Tying the Subscriber to the Publisher

This is the last step in our sample solution – now that we have both the Subscriber and the Publisher completely defined, we can use them in a simple program.

Code Snippet
  1. static void Main(string[] args)
  2.         {
  3.             MagazinePublisher mp = new MagazinePublisher();
  4.             Subscriber s1 = new Subscriber();
  5.             Subscriber s2 = new Subscriber();
  6.            
  7.            var removeMe1 = mp.Subscribe(s1);
  8.            var removeMe2 = mp.Subscribe(s2);
  9.  
  10.             // ‘setting’ this NewIssue property – will call notify on all the subscribers
  11.             mp.NewIssue = DateTime.Now.ToString(“MMMM”) + ” issue”;
  12.            
  13.             // Cleanup
  14.             removeMe1.Dispose();
  15.             removeMe2.Dispose();
  16.         }

 

Summary

There are several advantages of using these new interfaces to use in your own publish subscribe solution.

  1. Consistency, Uniformity – Everyone’s Publish Subscribe will now look the same – a great time-saver for new people brought onto a project.
  2. Moving away from events delegates –While events and delegates are great-  and can be used to provide the same implementation as the one above, one needs to be extra careful in removing (unsubscribing) from subscribed events. There are also a few other ‘gotchas’ in a typical publish subscribe pattern (that are discussed in detail here).

It isn’t everyday that one gets excited about the introduction of a couple of new interfaces – but given the ubiquitous applicability of the Publish Subscribe (or Observer) pattern, this is a fairly big deal. The only thing I disliked was the naming of the two interfaces – it leads to confusion. Which is why this article continues to refer to them as Publisher (IObservable) and Subscriber (IObserver).

Full Solution

Download .NET 4.0 IObservable Implementation Full Solution

Note – To compile successfully, your target framework must be set to .NET 4.0  (Right click the project properties and set the target framework). If you haven’t already, I would recommend using Visual Studio 2011 (beta) available here.

target_platform_dotnet_40

Anuj holds professional certifications in Google Cloud, AWS as well as certifications in Docker and App Performance Tools such as New Relic. He specializes in Cloud Security, Data Encryption and Container Technologies.

Initial Consultation

Anuj Varma – who has written posts on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.