簡體   English   中英

如何在F#界面中聲明事件?

[英]How should an event be declared in an F# interface?

現在,在F#中發布事件的標准方法如下:

type MyDelegate = delegate of obj * EventArgs -> unit

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()

    [<CLIEvent>]
    member this.OnMyEvent = myEvent.Publish

並且工作正常,包括能夠從其他.NET語言中消耗該事件(C#至少我已經測試過)。 但是如何讓這個事件出現在界面中呢? 這是我正在嘗試的......

type MyDelegate = delegate of obj * EventArgs -> unit

type IMyType =
    abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()

    interface IMyType with
        [<CLIEvent>]
        member this.OnMyEvent = myEvent.Publish

但是這不會編譯 - 接口中的成員會導致錯誤:“找不到與此覆蓋相對應的抽象或接口成員”。 我該如何在界面中聲明該事件? 或者是我的成員語法錯了嗎?

注意 - 這不是關於消耗F#中的C#事件或F#中的一般事件使用 - 接口方面是關鍵。

您需要在接口和實現上指定CLIEvent屬性。

open System;

type MyDelegate = delegate of obj * EventArgs -> unit

type IMyType =
    [<CLIEvent>]
    abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()

    interface IMyType with
        [<CLIEvent>]
        member this.OnMyEvent = myEvent.Publish

除了thr的答案之外,編寫在接口和實現中都不使用 CLIEvent屬性的代碼也是有效的:

type MyDelegate = delegate of obj * EventArgs -> unit

type IMyType =
    abstract member OnMyEvent : IEvent<MyDelegate, EventArgs>

type MyType () =
    let myEvent = new Event<MyDelegate, EventArgs> ()    
    interface IMyType with
        member this.OnMyEvent = myEvent.Publish

原因是F#編譯器可以通過兩種方式編譯事件:

  • 當您指定屬性時,事件將被編譯為帶有基礎addremove操作的.NET事件(與C#兼容)。

  • 如果未指定該屬性,則會將事件編譯為.NET屬性(帶有get ),該屬性返回IEvent<'T>類型的值(在F#核心庫中定義)。

因此,您的接口定義必須與實現相匹配(遺​​憾的是,自動推斷它非常棘手,因此編譯器不這樣做)。

你需要哪個選項? 如果您將代碼暴露給C#,那么您肯定需要CLIEvent 如果你只是從F#中使用它,那么它並不重要 - 但是,當你經常將事件傳遞給函數時,避免使用它可能更有效 - 例如在myTyp.OnMyEvent |> Event.map (...)
(在第一種表示中,事件需要包裝到IEvent<_>對象中,而在第二種情況下,它可以使用屬性獲取對象)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM