简体   繁体   English

如何正确观察非标准事件?

[英]How to properly observe non-standard events?

I am new to Reactive Extensions, and dealing with a COM Library that has events defined like this: 我是Reactive Extensions的新手,并且处理具有如下定义的事件的COM库:

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

How do I properly observe this? 我该如何正确观察这个? I tried using Observable.FromEvent() but as the event's parameters are not of type EventArgs I don't see how FromEvent() or FromEventPattern() is going to work. 我尝试使用Observable.FromEvent()但由于事件的参数不是EventArgs类型,我没有看到FromEvent()FromEventPattern()是如何工作的。

My current workaround is to attach a custom delegate to the event then invoke a Subject.OnNext() but I am guessing that's not how I should do it. 我目前的解决方法是将自定义委托附加到事件然后调用Subject.OnNext()但我猜这不是我应该怎么做。

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);
            });
        });

There is a special overload of FromEvent for it. FromEvent有一个特殊的重载。 It is a little goofy to get your head around but the function signature looks like: 让你的头脑有点傻,但功能签名如下:

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 concrete type. 转换函数是这里的重要部分,基本上你告诉Rx你的委托如何映射到具体类型。

In your scenario it ends up looking 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 is all this doing? 那么这一切又是什么呢? Internally, it is similar to what you are doing (I'll paraphrase what it does conceptually, since the implementation is slightly more complicated). 在内部,它与您正在做的类似(我将从概念上解释它的作用,因为实现稍微复杂一些)。 When a new subscription is made, the conversion function will be invoked with observer.OnNext passed in as the converter argument. 在进行新订阅时,将使用observer.OnNext作为converter参数传入converter函数。 This lambda will return a new MyDelegate instance that wraps the conversion function that we provided ( (id, price, amount) => ... ). 这个lambda将返回一个新的MyDelegate实例,它包装了我们提供的转换函数( (id, price, amount) => ... )。 This is what is then passed to the handler => MyEvent += handler method. 然后将其传递给handler => MyEvent += handler方法。

After that each time the event is fired it will call our lambda method and convert the passed arguments into an instance of MyArgs which is then delivered to converter / observer.OnNext . 在每次触发事件之后,它将调用我们的lambda方法并将传递的参数转换为MyArgs一个实例,然后传递给converter / observer.OnNext

In addition, to all that magic it will also take care of cleaning up the event handlers when you are done with it, gracefully hand exceptions down stream and will manage the memory over head by sharing a single event handler across multiple observers. 此外,对于所有这些魔法,它还将在完成后清理事件处理程序,优雅地向下传递异常并通过在多个观察者之间共享单个事件处理程序来管理内存。

Source code 源代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM