F# 记录的静态类型动态查找

F# 记录的静态类型动态查找,f#,F#,我试图静态地键入一个记录字段,然后返回该字段(唯一的项目只是为了准确) 所以它看起来像这样: type Item = {Id:int; Name:string} with member this.field fieldName = let info = getInfo fieldName this |> Seq.map (fun record -> FSharpValue.GetRecordField info) |>

我试图
静态地键入
一个
记录字段
,然后返回该
字段
(唯一的项目只是为了准确)

所以它看起来像这样:

type Item = {Id:int; Name:string}
  with
    member this.field fieldName =
      let info = getInfo fieldName
      this 
      |> Seq.map (fun record -> FSharpValue.GetRecordField info)
      |> Seq.distinct |> Seq.sort |> Array.ofSeq

let item = {Id = 1; Name = "First"}
let ids = item.field Item.Id
我在这个主题上找到了答案,但我认为使用
F#3.0
会有一个更好的方法,它也会扩展到
VB

尝试以下方法:

type Item = {Id:int; Name:string}
  with
    member x.field fieldName =
        let types = FSharpType.GetRecordFields(x.GetType()) |> Array.map (fun p -> p.Name)
        let values = FSharpValue.GetRecordFields(x)
        Array.zip types values
        |> Array.tryFind (fst >> (=) fieldName)
        |> Option.map (snd >> unbox)

let item = {Id = 1; Name = "First"}
let ids: int option = item.field "Id"
试试这个:

type Item = {Id:int; Name:string}
  with
    member x.field fieldName =
        let types = FSharpType.GetRecordFields(x.GetType()) |> Array.map (fun p -> p.Name)
        let values = FSharpValue.GetRecordFields(x)
        Array.zip types values
        |> Array.tryFind (fst >> (=) fieldName)
        |> Option.map (snd >> unbox)

let item = {Id = 1; Name = "First"}
let ids: int option = item.field "Id"

在这种情况下,您实际上不需要使用反射或动态查找。如果您使用返回记录字段的函数表示“查找”,那么它会非常好地工作。如果您使用的是
System.Func
而不是F#函数类型,那么它在所有.NET语言中都可以很好地使用:

type Item = 
  {Id:int; Name:string}

type ItemList =
  { Items : Item list }
  member this.Field(fn:System.Func<Item, 'T>) =
    this.Items
    |> Seq.map fn.Invoke
    |> Seq.distinct |> Seq.sort |> Array.ofSeq

let items = 
  { Items = [ {Id = 1; Name = "First"}
              {Id = 2; Name = "First"}
              {Id = 3; Name = "Second"} ] }

let names = items.Field(fun r -> r.Name)
类型项=
{Id:int;Name:string}
类型项目列表=
{项目:项目列表}

成员this.Field(fn:System.Func在这种情况下,您实际上不需要使用反射或动态查找。如果您使用返回记录字段的函数表示“查找”,它会非常好地工作。如果您使用
System.Func
而不是F#函数类型,那么它在所有.NET语言中都可以很好地使用:

type Item = 
  {Id:int; Name:string}

type ItemList =
  { Items : Item list }
  member this.Field(fn:System.Func<Item, 'T>) =
    this.Items
    |> Seq.map fn.Invoke
    |> Seq.distinct |> Seq.sort |> Array.ofSeq

let items = 
  { Items = [ {Id = 1; Name = "First"}
              {Id = 2; Name = "First"}
              {Id = 3; Name = "Second"} ] }

let names = items.Field(fun r -> r.Name)
类型项=
{Id:int;Name:string}
类型项目列表=
{项目:项目列表}
成员此.Field(fn:System.Func