【问题标题】:How can I get two lists, each containing the names of the required and optional properties of an F# record?如何获得两个列表,每个列表都包含 F# 记录的必需属性和可选属性的名称?
【发布时间】:2020-11-07 16:40:52
【问题描述】:

我有一个 F# 记录类型

type MyType = {
  Name : string
  Description : string option
}

我想要两个数组,一个包含必需属性的名称,一个包含可选属性。我该怎么做?

【问题讨论】:

    标签: .net reflection properties f# record


    【解决方案1】:
    open System.Reflection
    
    /// inspired by https://stackoverflow.com/questions/20696262/reflection-to-find-out-if-property-is-of-option-type
    let isOption (p : PropertyInfo) =
        p.PropertyType.IsGenericType &&
        p.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
    
    /// required and optional property names of a type 'T - in that order
    /// inspired by https://stackoverflow.com/questions/14221233/in-f-how-to-pass-a-type-name-as-a-function-parameter
    /// inspired by https://stackoverflow.com/questions/59421595/is-there-a-way-to-get-record-fields-by-string-in-f
    let requiredAndOptionalPropertiesOf<'T> =
        let optionals, requireds = typeof<'T>.GetProperties() |> Array.partition isOption
        let getNames (properties : PropertyInfo[]) = properties |> Array.map (fun f -> f.Name)
        (getNames requireds, getNames optionals)
    

    【讨论】:

    • 我更喜欢使用FSharpType.GetRecordFields typeof&lt;MyType&gt;,所以如果规范发生变化,它不会破坏任何东西。
    • 我添加了一个替代答案“反映”您的评论(双关语)。 FSharp.Reflection.FSharpType.GetRecordFieldstypeof&lt;'T&gt;.GetProperties() 更安全吗?
    • GetRecordFields 是 API 表面的一部分,即使属性映射到记录字段的内部实现发生变化,API 行为也将保持不变。话虽如此,如果 T 不是记录类型,GetRecordFields 将抛出,并且仅返回具有字段映射的属性(即,CompilationMappingAttribute 已应用),并尊重声明的顺序。
    【解决方案2】:

    这是考虑到@Asti 评论的替代答案:

    open System.Reflection
    
    let isOption (p : PropertyInfo) =
        p.PropertyType.IsGenericType &&
        p.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
    
    let requiredAndOptionalPropertiesOf<'T> =
        let optionals, requireds = FSharp.Reflection.FSharpType.GetRecordFields typeof<'T> |> Array.partition isOption
        let getNames (properties : PropertyInfo[]) = properties |> Array.map (fun f -> f.Name)
        (getNames requireds, getNames optionals)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      相关资源
      最近更新 更多