[VB.NET] 型パラメーター(Of T)を使って動的に型を指定してDictionaryからクラスに変換する

2021年10月7日

型パラメーター(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型を指定する方法でも動的に型指定することはできているのですが・・・
意味があるかどうかではなく、型パラメータ指定で書いてみたい!という場合のサンプルです。
使いどころについては、パッと思いつきませんが。

VB.NETVB.NET

Posted by itblogks