F#删除函数处理程序

时间:2013-01-26 03:15:49

标签: .net events f#

所以,我有一个我想在事件触发器上执行的函数,但我想稍后删除它。我该怎么做?我知道F#事件具有Add方法,该方法将函数添加为处理程序,但您无法删除此函数。我理解,但我找不到如何创建任何委托! (嗯, type Foo = delegate of type1 -> type2,但我不明白它的用法......)

编辑:这是一个更清晰的例子,我想做什么,在代码中:

// Define and publish event
let _someEvent = new Event<string>()
let SomeEvent = someEvent.Publish

// Normally, I'd do this to use it:
SomeEvent.Add (fun arg -> printfn "Argument: %s" arg)

// Trigger the event
someEvent.Trigger "Hello world"

但我的问题是我想在某个时候删除这个钩子。我知道这可能与代表有关......只是不知道如何做到这一点。

3 个答案:

答案 0 :(得分:7)

另一种选择是使用Subscribe方法并使用Dispose取消订阅:

// Define and publish event
let someEvent = new Event<string>()
let SomeEvent = someEvent.Publish

// Subscribe to event
let subscription =
    SomeEvent.Subscribe (fun arg -> printfn "Argument: %s" arg)

// Trigger the event
someEvent.Trigger "Hello world"

// Unsubscribe
subscription.Dispose()

答案 1 :(得分:5)

是的,只需使用处理程序。

// Define and publish event
let _someEvent = new Event<string>()
let SomeEvent = _someEvent.Publish

// wrap function in handler
let handler = Handler<string>(fun _ arg -> printfn "Argument: %s" arg)

// add
SomeEvent.AddHandler handler

// remove
SomeEvent.RemoveHandler handler

答案 2 :(得分:3)

您可以在F#中创建委托,就像创建任何其他对象一样。只需将函数传递给它的构造函数即可。您还可以使用RemoveHandler从任何.Net语言中删除事件中的处理程序。您需要确保将其传递给首先添加的相同委托。

此示例(您可以在FSI中运行)创建一个填充蓝色表单的PaintEventHandler,并将其添加到表单的Paint事件中。然后设置窗体上的按钮以从事件中删除绘制处理程序,并强制窗体重绘。

open System
open System.Drawing
open System.Windows.Forms

let form = new Form()

let paintHandler =
    PaintEventHandler( // The function is passed to the delegate constructor.
        fun sender e ->
            e.Graphics.Clear Color.CornflowerBlue
    )

form.Paint.AddHandler paintHandler // Handler added.

let btn = new Button()
btn.Text <- "Remove Handler"
btn.Width <- 200;
btn.Click.Add (fun e ->
    form.Paint.RemoveHandler paintHandler // Handler removed.
    form.Invalidate() // Redraw
)
form.Controls.Add btn

form.Show()

请务必注意AddHandler / RemoveHandler采用普通委托,但Add采用不同签名的功能。 (缺少sender参数。)