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)
我该如何解决以下任何问题来解决问题?
- 修改com库修复非标准事件类型错误。
- 使用explicit add_/remove_函数与observer.take/observer.subscribe。
- 在取消订阅之前,不使用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不要怀疑您需要这样的东西(。