There is a way to convert existing C# events to an IObservable<>. There is a good article here on this
public class SimpleEventSource
{
public event EventHandler<MyEventArgs> SimpleEvent;
// Normally this would be private (event is triggered internally)
// but for test purposes we make it public
public void FireSimpleEvent(MyEvent myevent)
{
EventHandler<MyEventArgs> tmp = SimpleEvent;
if (tmp != null)
{
tmp(this, new MyEventArgs(myEvent));
}
}
// This returns an IObservable (effectively an event pulisher)
public IObservable<EventPattern<MyEventArgs>> MyEventPublisher
{
get
{ // To consume SimpleEvent as an IObservable:
IObservable<EventPattern<MyEventArgs>> eventAsObservable = Observable.
FromEventPattern<MyEventArgs>(
ev => SimpleEvent += ev,
ev => SimpleEvent -= ev);
return eventAsObservable;
}
}
}
Note that MyEventArgs is something derived from EventArgs that allows access to the "MyEvent" instance, see below. Here is a tester:
public void TestSimpleEventSource()
{
var ses = new SimpleEventSource();
ses.FireSimpleEvent(new MyEvent("1st event")); // This one is missed
using (var subscription = ses.MyEventPublisher.Subscribe(
ev => Console.WriteLine(ev.EventArgs.MyEvent.Text + " fired")))
{
ses.FireSimpleEvent(new MyEvent("2nd event"));
ses.FireSimpleEvent(new MyEvent("3rd event"));
}
Console.WriteLine("Subscription cancelled");
}
and the output
2nd event fired 3rd event fired Subscription cancelled
Replacing C# Events using Reactive Extensions
Lets take this one step further, and completely replace the C# event with a reactive style event publisher
internal class SimpleEventSource
{
private Subject<MyEvent> _myEventSubject = new Subject<MyEvent>();
public IObservable<MyEvent> MyEventPublisher => this._myEventSubject.AsObservable();
public void FireSimpleEvent(MyEvent myEvent) => this._myEventSubject.OnNext(myEvent);
}
And the same test but using this class:
public void TestSimpleEventSource2()
{
var ses = new SimpleEventSource2();
ses.FireSimpleEvent(new MyEvent("1st event"));
using (var subscription = ses.MyEventPublisher.Subscribe(
ev => Console.WriteLine(ev.Text + " fired")))
{
ses.FireSimpleEvent(new MyEvent("2nd event"));
ses.FireSimpleEvent(new MyEvent("3rd event"));
}
Console.WriteLine("Subscription cancelled");
}
Here is the code for the simple event classes if it makes things clearer
public class MyEvent
{
public MyEvent(string text)
{
Text = text;
}
public string Text { get; private set; }
}
public class MyEventArgs : EventArgs
{
public MyEventArgs(MyEvent myEvent)
: base()
{
MyEvent = myEvent;
}
public MyEvent MyEvent { get; private set; }
}
No comments:
Post a Comment