我正在尝试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
。
答案 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"