有没有办法在F#中标识CLR事件实例?

时间:2019-02-25 01:05:00

标签: f#

在F#Interactive中工作时,我经常想对事件处理程序进行更改。只需在事件上调用Subscribe或Add或AddHandler函数,就会导致旧事件继续被调用,而这并不是本意。

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

当同一事件再次被订阅时,我尝试制作一个public void addToCage(Animal animal, int cageId) { int nbrCages = cages.size(); Cage tmp, cage; if (nbrCages == 0) { cage = new Cage(cageId); cage.setAnimal(animal); this.cages.add(cage); } else { boolean cageInUse = false; for (int i = 0; i < nbrCages; i++) { tmp = cages.get(i); if (tmp.getId() == cageId) { System.out.println("cage is full"); cageInUse = true; break; } } if (!cageInUse) { cage = new Cage(cageId); cage.setAnimal(animal); this.cages.add(cage); } } } 来调用Dispose():

Dictionary<IEvent,IDisposable>

不幸的是,事实证明,F#生成了一个新的IEvent实例,因此,天真地使用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)) =并不会削减它。

obj.Equals

我可以在IEvent中找到任何属性或字段来与所有者的其他实例以及所有者中的不同事件进行标识吗?

1 个答案:

答案 0 :(得分:2)

并非完全是问题的答案,但是我无法想到需要识别事件实例的许多其他情况,所以也许这已经足够了:

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对象。 / p>