How to properly observe non-standard events?

I'm new to Reactive Extensions and I'm dealing with a COM library that has events defined like this:

public delegate void MyDelegate(int requestId, double price, int amount);
public event MyDelegate MyEvent;

      

How to observe it correctly? I tried to use Observable.FromEvent()

, but since the event parameters are not type-specific EventArgs

, I don't see how FromEvent()

or would work FromEventPattern()

.

My current workaround is to attach a custom delegate to the event, then call Subject.OnNext()

, but I guess that's not how I should be doing it.

Here's an example of my current workaround:

        MyEvent += new MyDelegate((int requestId, double price, int amount) =>
        {
            Task.Run(() =>
            {
                var args = new MyArgs()
                {
                    requestId = requestId,
                    price = price,
                    amount = amount,
                };
                this.mySubject.OnNext(args);
            });
        });

      

+3


source to share


1 answer


There is a special overload for it FromEvent

. It's a bit dumb to put your head down, but the function signature looks like this:

IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, 
                                                         Action<TDelegate> addHandler, 
                                                         Action<TDelegate> removeHandler);

      

The conversion function is the important part here, basically you are telling Rx how your delegate maps to a specific type.

In your script, it looks something like this:

Observable.FromEvent<MyDelegate, MyArgs>(
  converter => new MyDelegate(
                  (id, price, amount) => converter(new MyArgs { 
                                                        RequestId = id, 
                                                        Price = price, 
                                                        Amount = amount
                                                       })
               ),
  handler => MyEvent += handler,
  handler => MyEvent -= handler);

      



So what does it all do? Internally, it is similar to what you are doing (I will paraphrase what it does conceptually, since the implementation is a little more complicated). When a new subscription is made, the conversion function will be called with observer.OnNext

passed as an argument converter

. This lambda will return a new instance MyDelegate

that wraps the transform function we provided ( (id, price, amount) => ...

). This is what is then passed to the method handler => MyEvent += handler

.

After that, every time the event fires, it will call our lambda method and convert the passed arguments into an instance MyArgs

, which is then delivered to converter

/ observer.OnNext

.

On top of all this magic, it also takes care of clearing the event handlers when you're done with it, gracefully handing exceptions downstream and managing memory overhead by sharing a single event handler across multiple observers.

Source

+4


source







All Articles