簡體   English   中英

如何使用 F# 中的接口更新和返回記錄

[英]How to update and return a record using an interface in F#

在 C# 中,我正在使用以下我想移入 F# 的函數:

public virtual void BringToTop(LayersEnum _TopMostLayer)
        {
            if (LayerName == _TopMostLayer)
            {
                ZIndex = 10;
                Visibility = Visibility.Visible;
            }
            else
            {
                ZIndex = DefaultZIndex;
                Visibility = Visibility.Hidden;
            }
        }

假設我有以下 F# 定義,這是如何在 F# 中實現的:

type DocumentRadioButtons = ChartLayer | WritingLayer | ImageLayer | TranscriptionLayer | PublisherLayer

module WritingLayer=

type Model = 
    {  Name: string
       Visibility: bool 
       DefaultZIndex: int
       ZIndex: int
    }
    interface ILayer with 
         member this.Name with get() = this.Name
         member this.Visibility with get() = this.Visibility
         member this.DefaultZIndex with get() = this.DefaultZIndex
         member this.ZIndex with get() = this.ZIndex

type ProgressNoteWin = {
       ConfirmState: ConfirmState option
       Encounter: view_doctor_encounter
       LastName: string
       DocumentLayer: DocumentRadioButtons
       WritingLayer: WritingLayer.Model
       ImageLayer: ImageLayer.Model
       ChartLayer: ChartLayer.Model
      } 

我非常失敗的嘗試是:

let BringToTop rb (layer:ILayer) = 
                   
                     if rb.ToString() = layer.Name then {layer with Visibility =true} else {layer with Visibility = false }
                

                { m with WritingLayer = BringToTop documentRadioButton m.WritingLayer},

錯誤:未定義記錄標簽“可見性”

感謝您的任何幫助。

#附錄:

最后,我想在 WritingLayer.Model、ImageLayer.Model 和 ChartLayer.Model 的不同記錄類型上實現接口,用作:

{m with WritingLayer = BringToTop rb m.WritingLayer; 
  ImageLayer = BringToTop rb m.ImageLayer; 
  ChartLayer = rb m.ChartLayer}

謝謝您的考慮。

此代碼將無法按原樣運行:

let BringToTop rb (layer:ILayer) = 
    if rb.ToString() = layer.Name then
        { layer with Visibility =true }
    else
        { layer with Visibility = false }

這是因為 F# 不會隱式向下轉換為實現接口的類型。

第一個可能的解決方案:

從傳遞ILayer切換到直接傳遞Model 然后您的代碼將起作用。

第二個可能的解決方案:

我假設既然你有一個接口,你想把它作為數據類型而不是模型類型本身傳遞。 如果是這種情況,那么我建議使用對象表達式來更新數據,如下所示:

let mkILayer visible (layer: ILayer) =
    { new ILayer with 
         member this.Name = layer.Name
         member this.Visibility = visible
         member this.DefaultZIndex = layer.DefaultZIndex
         member this.ZIndex = layer.ZIndex }
        
        
let BringToTop rb (layer:ILayer) =
    if rb.ToString() = layer.Name then
        mkILayer true layer
    else
        mkILayer false layer

第三個可能的解決方案

如果你對downcasting 沒問題,你可以像這樣隱藏你的第一layer定義:

let BringToTop rb (layer:ILayer) = 
    if rb.ToString() = layer.Name then
        let layer = layer :?> Model
        { layer with Visibility =true }
    else
        let layer = layer :?> Model
        { layer with Visibility = false }

但通常每當涉及向下轉換時,就會產生代碼異味,因此我真的建議改為構建接口的新實例。

我永遠無法以我想要的方式做到這一點——通過使用 ILayer 接口來更新和返回與之關聯的記錄類型。 我最感興趣的是更好的方法來做到這一點。

我最終所做的只是定義了三個特定的函數,每個類型一個:

let BringToTopWritingLayer rb layer:WritingLayer.Model =
                    if rb.ToString() = (layer :>ILayer).Name 
                    then 
                       {layer with Visibility = true}                  
                    else
                       {layer with Visibility = false} 

                let BringToTopImageLayer rb layer:ImageLayer.Model =
                    if rb.ToString() = (layer :>ILayer).Name 
                    then 
                       {layer with Visibility = true}                  
                    else
                       {layer with Visibility = false} 

                let BringToTopChartLayer rb layer:ChartLayer.Model =
                    if rb.ToString() = (layer :>ILayer).Name 
                    then 
                       {layer with Visibility = true}                  
                    else
                       {layer with Visibility = false} 

用法如下:

{ m with DocumentLayer = documentRadioButton; 
                      WritingLayer = BringToTopWritingLayer documentRadioButton m.WritingLayer;
                      ImageLayer = BringToTopImageLayer documentRadioButton m.ImageLayer;
                      ChartLayer = BringToTopChartLayer documentRadioButton m.ChartLayer}

這看起來非常多余,但它似乎可以正確編譯。

一個更好的答案將不勝感激。

暫無
暫無

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

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