Click here to Skip to main content
Click here to Skip to main content
Go to top

Implementing the GeoCoordinateWatcher as a Reactive Service

, 28 Jan 2013
Rate this:
Please Sign up or sign in to vote.
With Rx, events are first class citizens that can be passed around and composed as needed in a very simple way.

With Rx, events are first class citizens that can be passed around and composed as needed in a very simple way.

The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Using Rx, developers represent asynchronous data streams with Observables, query asynchronous data streams using LINQ operators, and parameterize  the concurrency in the asynchronous data streams using Schedulers. Simply put, Rx = Observables + LINQ + Schedulers.” – from the MSDN page.Paulo Morgado

The library also provides a considerable amount of helpers that make it easy to warp events into observables.

Wrapping the GeoCoordinateWatcher as a reactive service is quite simple. All it takes is creating observables and exposing the events as observables:

public class GeoCoordinateReactiveService : IGeoCoordinateReactiveService, IDisposable
{
    private readonly GeoCoordinateWatcher geoCoordinateWatcher = new GeoCoordinateWatcher();

    public GeoCoordinateReactiveService()
    {
        this.StatusObservable = Observable
            .FromEventPattern<GeoPositionStatusChangedEventArgs>(
                handler => geoCoordinateWatcher.StatusChanged += handler,
                handler => geoCoordinateWatcher.StatusChanged -= handler);

        this.PositionObservable = Observable
            .FromEventPattern<GeoPositionChangedEventArgs<GeoCoordinate>>(
                handler => geoCoordinateWatcher.PositionChanged += handler,
                handler => geoCoordinateWatcher.PositionChanged -= handler);
    }

    public IObservable<EventPattern<GeoPositionStatus> StatusObservable { get; private set; }

    public IObservable<EventPattern<GeoPosition<GeoCoordinate>> PositionObservable { get; private set; }
}

And now, instead of the StatusChanged and PositionChanged events we have respectively the StatusObservable and PositionObservable as a stream of EventPattern<TEventArgs> instances.

But the EventPattern<TEventArgs> class includes the source of the event and an the event arguments in properties which is far more than we need in this case. With normal LINQ operators we can convert the streams of EventPattern<TEventArgs> instances in streams of the desired values.

public class GeoCoordinateReactiveService : IGeoCoordinateReactiveService, IDisposable
{
    private readonly GeoCoordinateWatcher geoCoordinateWatcher = new GeoCoordinateWatcher();

    public GeoCoordinateReactiveService()
    {
        this.StatusObservable = Observable
            .FromEventPattern<GeoPositionStatusChangedEventArgs>(
                handler => geoCoordinateWatcher.StatusChanged += handler,
                handler => geoCoordinateWatcher.StatusChanged -= handler)
            .Select(ep => ep.EventArgs.Status);

        this.PositionObservable = Observable
            .FromEventPattern<GeoPositionChangedEventArgs<GeoCoordinate>>(
                handler => geoCoordinateWatcher.PositionChanged += handler,
                handler => geoCoordinateWatcher.PositionChanged -= handler)
            .Select(ep => ep.EventArgs.Position);
    }

    public IObservable<GeoPositionStatus> StatusObservable { get; private set; }

    public IObservable<GeoPosition<GeoCoordinate>> PositionObservable { get; private set; }
}

And to use these observables all it is needed is to subscribe to them:

geoCoordinateWatcherService.StatusObservable
    .Subscribe(this.OnStatusChanged);

geoCoordinateWatcherService.PositionObservable
    .Subscribe(this.OnPositionChanged);

But, usually, we want to use these values in view model to bind to the UI and, consequently, we want this to happen in the UI thread:

geoCoordinateWatcherService.StatusObservable
    .ObserveOnDispatcher()
    .Subscribe(this.OnStatusChanged);

geoCoordinateWatcherService.PositionObservable
    .ObserveOnDispatcher()
    .Subscribe(this.OnPositionChanged);

It’s as simple as that!

Resources:

License

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

Share

About the Author

Paulo Morgado
Software Developer (Senior) Paulo Morgado
Portugal Portugal

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 28 Jan 2013
Article Copyright 2013 by Paulo Morgado
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid