簡體   English   中英

F# Inheritance 具有多個基礎構造函數和事件

[英]F# Inheritance with Multiple Base Constructors and Events

目前有一個 F# class 實現如下:

namespace MultiLanguage.FSharpClassLibrary

open MultiLanguage.CSharpClassLibrary
open System
open System.Runtime.Serialization

[<Serializable>]
type SerializableFSharpClass =
    inherit SerializableBaseClass

    new () as this =
        { inherit SerializableBaseClass() }
        then
        this.InitFields()

    new (other: SerializableFSharpClass) as this =
        { inherit SerializableBaseClass(other) }
        then
        this.InitFields()
        // Copy Properties

    new (info : SerializationInfo, context : StreamingContext) as this
        = { inherit SerializableBaseClass(info, context) } then
        this.InitFields()
        // Deserialize Properties

    // Let binding does not work
    // because of the following error:
    // FS0963: This definition may only be used in a type with a primary constructor.
    //let myFSharpEvent = new Event<EventHandler<EventArgs>,EventArgs>()
    //[<CLIEvent>]
    //member this.FSharpEvent = myFSharpEvent.Publish

    // Event raising does not work with member private
    // because new instances are created with every access to FSharpEvent:
    //member private this.myFSharpEvent = new Event<EventArgs>()
    //[<CLIEvent>]
    //member this.FSharpEvent = this.myFSharpEvent.Publish
    //member this.RaiseFSharpEvent e = this.myFSharpEvent.Trigger e

    // Event raising works with val mutable
    // but requires additional initialization of myFSharpEvent
    [<DefaultValue>]
    val mutable myFSharpEvent : Event<EventHandler<EventArgs>,EventArgs>
    [<CLIEvent>]
    member this.FSharpEvent = this.myFSharpEvent.Publish
    member this.RaiseFSharpEvent e = this.myFSharpEvent.Trigger e

    member private this.InitFields()
        =
        this.myFSharpEvent <- new Event<EventHandler<EventArgs>,EventArgs>()

我想知道是否有更簡單的方法讓 CLIEvent 與 let 綁定一起使用,並且仍然根據需要使用所有基本 class 構造函數,以最終擺脫 InitFields 方法。

恐怕你在這里無能為力。 問題在於,只有當您始終只調用單個基本 class 構造函數時,才能使用具有隱式構造函數的類的輕量級 F# 語法。 您的情況並非如此,因此您必須使用顯式語法。

如果在構造函數的{.. }部分初始化事件,則可以避免DefaultValue屬性,您可以在其中調用基本 class 構造函數並初始化所有字段。 這對您並沒有太大幫助,但這是我能想到的唯一調整:

type A = 
  new (n:int) = {}
  new (s:string) = {}

type B =
  inherit A

  new (n:int) = { 
    inherit A(n) 
    myFSharpEvent = new Event<_, _>() }
  new (s:string) = { 
    inherit A(s) 
    myFSharpEvent = new Event<_, _>() }

  val mutable myFSharpEvent : Event<EventHandler<EventArgs>,EventArgs>
  member this.FSharpEvent = this.myFSharpEvent.Publish
  member this.RaiseFSharpEvent e = this.myFSharpEvent.Trigger e

這會導致一些最小的代碼重復 - 我認為這很好,但您也可以定義一個幫助程序 function (但在 class 之外,因為您不能在此類中使用let )。

總結可能是,我將把所有重要的邏輯從這個 class 中移開,只把它當作一個包裝器,以使我漂亮的 F# 代碼與你需要的任何 .NET 基礎設施兼容。

暫無
暫無

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

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