Reactive Extensions (Rx) – Part 2 – Wrapping C# Events

Sometimes it is not possible to replace a C# event with a Reactive Extensions (Rx) event entirely. This is usually because we are implementing an interface which has a C# event and we don’t own the interface.

However, as I’ll show in this post, its possible to create IObservable<T> wrappers for C# events and even to hide the C# events entirely from consumers of the class.

The method of wrapping C# events depends on the type of event handler used. Below are the three type of event handler and the method of wrapping them with an observable event.

Wrapping an EventHandler C# Event

The FromEventPattern method is used to wrap the event. Notice we have to specify delegates for subscribing (+=) and unsubscribing (-=) to the event.

Wrapping an EventHandler<T> C# Event

This example is much the same as the last, except we have to deal with the event arguments. The FromEventPattern method returns an  EventPattern<T> object, which contains the sender and the event arguments. We’re only interested in the contents of the event arguments, so we use a Select to return just the BunnRabbits property.

Wrapping a Custom Event Handler C# Event

Some C# events use a custom event handler. In this case we have to specify the type of the event handler as a generic argument in the FromEventPattern method.

Hiding Existing Events Using Explicit Interface Implementation

The disadvantage of the above approach is that we now have two ways to access our event. One with the old style C# event and the other with our new Reactive Extensions event. With a bit of trickery we can hide the C# event in some cases.

The INotifyPropertyChanged interface is very commonly used by XAML developers. It has a single event called PropertyChanged. To hide the PropertyChanged C# event we can explicitly implement the interface (Click here for details on implicit versus explicit implementations of interfaces). Secondly, we wrap the event as we did before.

Now the PropertyChanged C# event can only be accessed by first casting the object to INotifyPropertyChanged (Binding in XAML languages, which uses this interface continues to work). Our new Reactive Extensions observable event is now the default method of subscribing for property changed events.

Summing Up

So it may not always be possible to get rid of, dare I say it legacy C# events but we can certainly wrap them with Reactive Extension observables and even hide them altogether.