繁体   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