f# - 有没有办法识别 F# 中的 CLR 事件实例?

标签 f#

当我在 F# Interactive 中工作时,我经常想要对事件处理程序进行更改。简单地对事件调用 Subscribe 或 Add 或 AddHandler 函数会导致旧事件继续被调用,这很少是意图。

一种解决方案是使用它返回的 IDisposable,但这需要在您自己的代码中跟踪 IDisposable,这对于探索性任务来说很麻烦。

我尝试过制作 Dictionary<IEvent,IDisposable>当再次订阅同一事件时调用 Dispose():

let events = Dictionary<obj, IDisposable>()
let subonce (e:IEvent<'h,'e>) (handler: 'e -> unit) =
    if events.ContainsKey e then
        events.[e].Dispose()
        events.Remove e |> ignore
    let d = e.Subscribe handler
    events.Add (e,d) |> ignore

let w = Window()
w.Show()

//Running this line in FSI a second time onward should Dispose() the previous subscription
subonce w.MouseUp (fun e -> printfn "%A" <| e.GetPosition(w))

不幸的是,事实证明,F# 生成了一个新的 IEvent 实例,因此天真地使用 =obj.Equals没有削减它。

> w.MouseUp;;
val it : IEvent<Input.MouseButtonEventHandler,Input.MouseButtonEventArgs> =
  <published event> {addHandler = <fun:it@5-70>;
                     createHandler = <fun:it@5-72>;
                     removeHandler = <fun:it@5-71>;}

> w.MouseUp;;
val it : IEvent<Input.MouseButtonEventHandler,Input.MouseButtonEventArgs> =
  <published event> {addHandler = <fun:it@6-74>;   //note that these functions are of a different anonymous instance
                     createHandler = <fun:it@6-76>;
                     removeHandler = <fun:it@6-75>;}

我可以在 IEvent 中找到任何属性或字段,这些属性或字段可以根据所有者的其他实例以及该所有者中的不同事件来识别它吗?

最佳答案

不完全是问题的答案,但我想不出您需要识别事件实例的许多其他场景,所以也许这已经足够好了:

type OneHandler<'e> = { mutable h : 'e -> unit }
let onehandler (e:IEvent<'h,'e>) =
    let h = { h = fun _ -> () }
    e.Subscribe(fun e -> h.h e) |> ignore
    h

let w = Window()
let wmouseup = onehandler w.MouseUp

wmouseup.h <- (fun e -> printfn "%A" <| e.GetPosition(w))

这样,通过仅评估对 wmouseup.h 的赋值,我们就可以更改事件处理程序,而无需重新启动 w 或调整 IDisposableHandler 对象。

关于f# - 有没有办法识别 F# 中的 CLR 事件实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54858203/

相关文章:

F#:没有默认构造函数作为类型参数的类?

visual-studio - Visual Studio 2013 Ultimate 调试器未显示整个列表

F# 记录结构比较排序

algorithm - 如何在 AST 中查找标识符的用法?

generics - F#独特的重载方法

f# - 使用 FsUnit.Xunit 断言异常消息

wpf - 使用 WPF 的 F# 事件驱动 MVVM

f# - 在 F# 中,是否有一种功能方法可以将平面数组转换为一组条目的数组?

f# - 使用 System.IO.Compression.ZipArchive 进行压缩在 F# 代码中不起作用

winforms - F# : what is the deal with the flicker? 中的双缓冲