[VB.NET] 型パラメーター(Of T)を使って動的に型を指定してDictionaryからクラスに変換する
型パラメーター(Of T)で変換するサンプル
Dictionary(Of String, Object)のデータを、型パラメーターで指定したクラスに変換するサンプルです。
キー(String)/ 値(Object)の組み合わせにして、「record」クラスのプロパティと一致するようにしています。
main()で作成しているテスト用のディクショナリーは、
・ src ┳ item1
・ ・ ┣ item2
・ ・ ┗ item3 ┳ param1
・ ・ ・ ・ ・ ┗ param2
という構造にしてあります。
クラスの中にプリミティブ型のプロパティしか持たない場合の方が稀だと思うので、階層にしてみました。
これを「record」クラスに変換します。
キー名からプロパティ名を特定しているので、ディクショナリのキーと「record」クラスのプロパティ名が一致している必要があります。
main()の中では DictionaryToModel(of T) を呼び出して変換しているわけですが、実際の変換処理はType型を使ってリフレクションでおこなっています。最後にその結果を型パラメータに変換しているだけです。
以下はコード
Module main
''' <summary>
''' メイン
''' </summary>
Sub main()
'変換テスト用のディクショナリを作成
Dim src As New Dictionary(Of String, Object)
src.Add("item1", "テスト")
src.Add("item2", 123)
src.Add("item3", New Dictionary(Of String, Object) From {{"param1", "パラメータ"}, {"param2", 456}})
'型パラメーター(Of T)を使って動的に型を指定してDictionaryからクラスに変換する
Dim rec As record
rec = DictionaryToModel(Of record)(src)
Console.WriteLine(rec.item1)
Console.WriteLine(rec.item2)
Console.WriteLine(rec.item3.param1)
Console.WriteLine(rec.item3.param2)
End Sub
''' <summary>
''' 型パラメーター(Of T)を使って動的に型を指定してDictionaryからクラスに変換する
''' </summary>
''' <typeparam name="T">型パラメーター</typeparam>
''' <param name="src">ディクショナリー</param>
''' <returns>変換後のレコード</returns>
Friend Function DictionaryToModel(Of T)(ByVal src As Dictionary(Of String, Object)) As T
Return CType(DictionaryToModel(GetType(T), src), T)
End Function
''' <summary>
''' Type型を使って動的に型を指定してDictionaryからクラスに変換する
''' </summary>
''' <param name="typ">Type型</param>
''' <param name="src">ディクショナリー</param>
''' <returns>変換後のレコード</returns>
Friend Function DictionaryToModel(ByVal typ As Type, ByVal src As Dictionary(Of String, Object)) As Object
Dim result As Object = Activator.CreateInstance(typ)
Dim pi As Reflection.PropertyInfo
Dim val As Object
For Each item As KeyValuePair(Of String, Object) In src
pi = typ.GetProperty(item.Key)
If TypeOf item.Value Is Dictionary(Of String, Object) Then
'itemがDictionaryなら再帰呼び出し
val = DictionaryToModel(pi.PropertyType, CType(item.Value, Dictionary(Of String, Object)))
Else
val = item.Value
End If
pi.SetValue(result, val)
Next
Return result
End Function
End Module
''' <summary>
''' レコードクラス
''' </summary>
Public Class record
Public Property item1 As String
Public Property item2 As Integer
''' <summary>
''' レコードパラメータークラス
''' </summary>
''' <returns></returns>
Public Property item3 As record_param
End Class
''' <summary>
''' レコードパラメータークラス
''' </summary>
Public Class record_param
Public Property param1 As String
Public Property param2 As Integer
End Class
型パラメーター(Of T)を使って動的に型を指定してDictionaryからクラスに変換してみました。
Type型を指定する方法でも動的に型指定することはできているのですが・・・
意味があるかどうかではなく、型パラメータ指定で書いてみたい!という場合のサンプルです。
使いどころについては、パッと思いつきませんが。