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