Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert an event to an IObservable when it doesn't conform to the standard .NET event pattern

I have an delegate that looks like this:

public delegate void MyDelegate(int arg1, int arg2);

And an event that looks like this:

public event MyDelegate SomethingHappened;

Is there some easy way to create an IObservable sequence for this event? I'd like to do something like this (but it doesn't compile):

var obs = Observable.FromEventPattern<int, int>(this, "SomethingHappened");
var subscription = obs.Subscribe(x,y => DoSomething(x, y));

....

private void DoSomething(int value1, int value2)
{
...
}
like image 211
pete757 Avatar asked Sep 10 '14 14:09

pete757


2 Answers

There is a way to do this using Observable.FromEvent as follows.

Lets create a class Test to encapsulate the delegate and event definition:

public class Test
{   
    public delegate void MyDelegate(int arg1, int arg2);

    public event MyDelegate SomethingHappened;

    public void RaiseEvent(int a, int b)
    {
        var temp = SomethingHappened;
        if(temp != null)
        {
            temp(a, b);
        }
    }    
}

Now, because the delegate has two arguments which are not neatly packaged into a subclass of EventArgs, we must use a conversion function to package them into a suitable containing type. If you recall the signature of the OnNext method of IObservable it should be clear why we have to do this - we can only supply a single argument here.

You can create your own type for this, but I will be lazy and use a Tuple<int,int>. We can then use the overload of Observable.FromEvent with the conversion function as follows:

var test = new Test();

var obs = Observable.FromEvent<Test.MyDelegate, Tuple<int,int>>(
    handler => (a, b) => handler(Tuple.Create(a,b)),
    h => test.SomethingHappened += h,
    h => test.SomethingHappened -= h
);

To be clear, what we are supplying in that first parameter is a function that accepts an OnNext handler (in this case of type Action<Tuple<int,int>>) and returns a delegate that can be subscribed to the event (of type MyDelegate). This delegate will be invoked for each event and will in turn invoke the OnNext handler passed in from the Subscribe call. Thus we will end up with a stream of type IObservable<Tuple<int,int>>.

With obs in place, we can subscribe like so:

var subscription = obs.Subscribe(x => Console.WriteLine(x.Item1 + " " + x.Item2));

And test with this:

test.RaiseEvent(1, 2);
like image 192
James World Avatar answered Nov 14 '22 21:11

James World


I haven't used Observable before, but it looks like the Observable.FromEvent method does what you want: http://msdn.microsoft.com/en-us/library/hh229271(v=vs.103).aspx

like image 24
Chris Pitman Avatar answered Nov 14 '22 21:11

Chris Pitman