Reputation: 6543
Through some API i get access to kind of Table in the form of a sequence of Gereric.Dictionary. Because the table has a schema I want to extract records out of it. Here is what i have ?
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}
Can I make the function extractPerson
more generic, like
let extract<'T> (gd:Dictionary<string,obj>) =
// ???
so that I can call ?
extract<Person> gd
Upvotes: 0
Views: 445
Reputation: 243061
As mentioned in the comments, this is something that can only be done using reflection. The following works for your simple example, but it is very limited:
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
It uses GetRecordFields
to find out what the names of the fields are, then it gets their values from the dictionary and calls MakeRecord
to create the record value. This is not super efficient, but depending on what you need, it might just work good enough for you.
Now you can use it as follows:
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
Upvotes: 5