2016-07-05 14 views
0

いくつかのAPIを介して、Gereric.Dictionaryのシーケンスの形式でテーブルの種類にアクセスできます。テーブルにはスキーマがありますから、レコードを抽出したいのです。ここには何がありますか?私が呼び出すことができるように一般辞書からレコードを抽出するには?

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} 

は私が

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

のように、機能extractPersonは、より一般的なことはできますか?

extract<Person> gd 
+0

どのように '' <'T>仕事を抽出します:次のように

今、あなたはそれを使用することができますか?辞書の各キーを使用してレコードの同じ名前のプロパティを設定する方法はありますか? – DaveShaw

+0

はい、ちょうど辞書 – fbehrens

+3

のFキーに一致するキーでレコードを記入してください。リフレクションや[DLR](https://www.nuget.org/packages/FSharp.Interop)のようなものを使用する必要があります。 .Dynamic /)をこれに割り当てます。コンパイル時にキーのリストを知っていれば、コード生成や型プロバイダを調べることができます(ただし、これはボックスの外にあるとは限りません)。 – DaveShaw

答えて

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 

それはそれは辞書から値を取得し、レコードを作成するMakeRecordを呼び出して、フィールドの名前が何であるかを見つけるためにGetRecordFieldsを使用しています値。これは超効率的ではありませんが、必要なものによっては、あなたのために十分に機能するかもしれません。

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 
+0

この大きな助けをありがとう。私には、これはすべてのレコードタイプで動作するように見えますが、パフォーマンスによっては制限されますか? – fbehrens

+0

私は、これを実用的にするために必要な多くの機能があるという意味で制限されていると思います。ネストされたレコードはどうですか?もし値が 'int'でもレコードは' float'を期待していますか?基本的には、これはトリックです。 –

関連する問題