如何从通用字典中提取记录?

时间:2016-07-05 14:30:02

标签: f#

通过一些API,我可以以一系列Gereric.Dictionary的形式访问Table。因为该表有一个模式,我想从中提取记录。这是我的意思?

open System.Collections.Generic

let gd = Dictionary<string,obj> ()
gd.Add("name", "Frank")
gd.Add("age", 24)
gd.Add("born", 1999)

type Person = { name : string
                age  : int}

let extractPerson (gd:Dictionary<string,obj>) = 
 { name = gd.["name"] :?> string
   age  = gd.["age"] :?> int}

我可以使函数extractPerson更通用,比如

let extract<'T> (gd:Dictionary<string,obj>) =
  // ???

以便我可以打电话?

extract<Person> gd

1 个答案:

答案 0 :(得分:5)

正如评论中所提到的,这只能通过反射来完成。以下适用于您的简单示例,但它非常有限:

open Microsoft.FSharp.Reflection

let extract<'T>(gd:Dictionary<string,obj>) = 
  let flds = FSharpType.GetRecordFields(typeof<'T>)
  let vals = [| for f in flds -> gd.[f.Name] |]
  FSharpValue.MakeRecord(typeof<'T>, vals) :?> 'T

它使用GetRecordFields来查找字段的名称,然后从字典中获取它们的值并调用MakeRecord来创建记录值。这不是超级高效的,但根据你的需要,它可能对你来说足够好。

现在您可以按如下方式使用它:

let gd = Dictionary<string,obj> ()
gd.Add("name", "Frank")
gd.Add("age", 24)
gd.Add("born", 1999)

type Person = { name : string; age  : int}    
extract<Person> gd