Paulo Morgado

.NET Development & Architecture

This Blog

Syndication

Search

Tags

News

Unit Test Today! Get Typemock Isolator!

Projects

Books

 

Visitors

Visitor Locations

Community

Email Notifications

Archives

Profile

Disclaimer

The opinions and viewpoints expressed in this site are mine and do not necessarily reflect those of Microsoft, my employer or any community that I belong to. Any code or opinions are offered as is. Products or services mentioned are purchased by me, made available to me by my employer or the manufacturer/vendor which doesn't influence my opinion in any way.

Implementing The GeoCoordinateWatcher As A Reactive Service

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.

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 thes 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:

Published Wed, Jan 2 2013 2:35 by Paulo Morgado

Comments

# Using The GeoCoordinateReactiveService@ Sunday, January 20, 2013 7:50 PM

Having created an Rx wrapper over the GeoCoordinateWatcher on a previous post , in this post I’ll demonstrate

Paulo Morgado

Leave a Comment

(required) 
(required) 
(optional)
(required) 
If you can't read this number refresh your screen
Enter the numbers above: