F#反应性订阅COM的非标准事件



i有一个本机com库(我可以修改(,并且我有一个f#应用程序试图与项目中引用的iNterop库一起使用Rx的事件。

let events = obj :?> _IInteropEvents_Event
let disposable = 
    Observable.take 1 events.ComEventArrived
    |> Observable.subscribe (fun sender data -> ()) // sender : ISender, data : IData

我不完全理解的错误消息是:

事件" comventarrived"具有非标准类型。如果这个事件是 用另一种CLI语言声明,您可能需要访问此事件 使用显式add_comeventArrived和Remove_comeventArrived 事件的方法。如果此事件在f#中声明,请进行类型 事件的实例化是" idelegateevent< >"或 'ievent< ,_>'。

我不介意使用add_ComEventArrived,但我不知道如何使用Observable

使此工作

奇怪的是,ComEventArrived有2个关于内部Interop类型的参数,如果我尝试订阅其他简单的事件,这些事件只是元帅,它有效,并且没有"非标准类型"错误:

let events = obj :?> _ISnapshotEvents_Event
let disposable = 
    Observable.take 1 events.SnapshotEventArrived
    |> Observable.subscribe (fun sender -> ()) // sender : IUnknown (unit)

我该如何解决以下任何问题来解决问题?

  1. 修改com库修复非标准事件类型错误。
  2. 使用explicit add_/remove_函数与observer.take/observer.subscribe。
  3. 在取消订阅之前,不使用Mutable/lock之前发射事件的其他方式 n 次。

我已经阅读了:

  • so:20819860
  • so:31896881
  • so:41439213
  • 节流f#事件

我对com Interop不了解,但是我可以举一个将非标准事件变成IObservable的示例,这应该涵盖您的第二点。

非标准事件的一个示例是AppDomain.CurrentDomain.AssemblyResolve,其中事件处理程序需要返回Assembly而不是返回unit。要使用add_remove_功能将其包装到IObservable中,您可以写下:

let assemblyResolve = 
  { new IObservable<_> with
      member x.Subscribe(observer) =
        let handler = ResolveEventHandler(fun o a -> 
          let mutable res = None 
          observer.OnNext((o, a, fun a -> res <- Some a))
          res.Value )
        AppDomain.CurrentDomain.add_AssemblyResolve(handler)
        { new IDisposable with
            member x.Dispose() = 
              AppDomain.CurrentDomain.remove_AssemblyResolve(handler) } }

我们使用F#对象表达式创建IObservable的新实现。在Subscribe成员中,我们创建一个ResolveEventHandler并使用add_AssemblyResolve添加。Subscribe的结果是IDisposable实现,然后使用remove_AssemblyResolve

这里的丑陋hack是观察者的OnNext函数无法返回任何内容,因此我们将其与参数一起给它一个三元素的元组,也给它一个设置返回值的函数(这是AssemblyResolve特定的,所以我i不要怀疑您需要这样的东西(。

相关内容

  • 没有找到相关文章

最新更新