用于记录的静态类型动态查找

时间:2013-09-26 23:49:02

标签: f#

我正在尝试statically type一个record field,然后返回field(仅限确切的唯一项目)。

所以它看起来像这样:

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

我在这个问题上找到了this old write up by Tomas Petricek,但我认为F# 3.0会有一个更好的方法,也可以延伸到VB

2 个答案:

答案 0 :(得分:4)

在这种情况下,您实际上不需要使用反射或动态查找。如果使用返回记录字段的函数表示“查找”,它的工作效果非常好。如果你使用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)

答案 1 :(得分:0)

试试这个:

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"