0

我正在尝试statically typearecord 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

我发现了 Tomas Petricek关于这个主题的这篇旧文章,但我认为会有更好的方法,F# 3.0它也可以扩展到VB.

4

2 回答 2

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)
于 2013-09-27T00:38:44.843 回答
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"
于 2013-09-27T00:33:47.197 回答