日期:2014-05-17  浏览次数:21263 次

C# - Dabble with IObservable<T> and IObserver<T>

Delegate offers some nice features of observable pattern, however, there are some limiation on the delgate implemented observable patterns.

?

Why not Delegate

?

For onething, there is no way to know when the subject no longer tick; the subject may become out of interest if it does not tick updates; But with the passive mode of delegate, you do not know that a subject is become inactive as the pattern itself is passive (there are some workaround , indeed by you provide another event to nofity that the subject is beome inactive);

?

For another, there is no way to descrimate against a valid udpate from error conditions, using some sentry value as the update event args could serve in some cases, but that is a botch/tinker/bumble/bungle rather than good solution, it is a smell design to intermingle the normal message channel with the error message channel;

?

for yet another, there is no way to know when/how to remove the IObserver from the notification list, a simple -= may unsusbscribe the event listener, but there would exist a huge amount of house keeping work that needs to be addresseed when an Observer go out of scope. Better, a Disposable is better in situation like this;?

?

?

IObservable<T> and IObserver<T> pattern provides the cure;

?

It has provide the following.

  • IObservable<T>.Subscribe(IObserver<T> observer): this notify the IObserver to add the observer to its notification list;

the return value of IDisposable, which satisify the the question of "how to remove teh IObserver from the notification list";

  • IObserver<T>.OnComplete: This notifies that the provider has finished sending push-based notification

this has the functionality of telling the observers when the subject (provider) will/has become inactive. and on receiving the information, teh IObserver can use the IDispose method that it receives in the Subscribe step to unsubscibe itself from the notification and do the proper uninitialization.

  • IObserver<T>.OnErro(Exception erorr): this satisfy the question of how to notify the client when some error condition has happens.?
  • IObserver<T>.OnNext(): this satisfy the basic requirement of the Provider notifies the clien when there is update coming.

?

Below shows the code an example IObservable<T> implementation, the T is of type Location, which represent some Location information.

?

?

?

namespace PushBasedNotificationTest
{
  public struct Location
  {

    double lat, lon;

    public Location(double latitude, double longitude)
    {
      this.lat = latitude;
      this.lon = longitude;
    }

    public double Latitude
    {
      get { return this.lat; }
    }
    public double Longitude
    {
      get { return this.lon; }
    }

  }
}
?

?

LocationTracker is our impl ?of IObservable<Location>, here it is:

?

?

namespace PushBasedNotificationTest
{
  public class LocationTracker  : IObservable<Location>
  {
    public LocationTracker()
    {
      // initialize the list of Observers to the Updates
      observers = new List<IObserver<Location>>();
    }

    // you need a collection of Observers
    // on which you can send the notification 
    private List<IObserver<Location>> observers;


    // Subscribe an observer (IObserver<T>) to the observer list
    // notice the return value of the Subscribe method, 
    // which is of type IDisposable.
    // normally the Observer will store the return value 
    // and call the Dispose method from the IDisposable interface 
    // the common work done in the Disposable method is to remove itself from