APIへのリクエストパラメータ作成やログ出力などで、クラスや匿名型のオブジェクトを「プロパティ名」と「値」のペア(キーバリュー形式)に変換したい場合があります。
リフレクションを使用することで、型定義に依存しない汎用的な変換メソッドを作成できます。ここでは、任意のオブジェクトを Dictionary<string, string> に変換する実装例を解説します。
目次
実装サンプル:PCスペック情報の辞書変換
以下のコードでは、PCのスペック情報を格納したクラス(または匿名型)を、プロパティ名をキーとする辞書データに変換し、コンソールに出力します。
サンプルコード
using System;
using System.Collections.Generic;
using System.Reflection;
public class Program
{
public static void Main()
{
// 1. 変換元のデータ(匿名型でもクラスでも可)
var gamingPc = new
{
Model = "Alienware X15",
Cpu = "Core i9-12900H",
RamGB = 32,
SsdTB = 1.0,
IsLaptop = true
};
// 2. オブジェクトをDictionaryに変換
Dictionary<string, string> specSheet = ObjectToDictionary(gamingPc);
// 3. 結果の表示
Console.WriteLine("--- スペック一覧 ---");
foreach (var item in specSheet)
{
Console.WriteLine($"{item.Key, -10}: {item.Value}");
}
}
/// <summary>
/// 任意のオブジェクトのパブリックプロパティを辞書に変換する
/// </summary>
/// <param name="data">変換対象のオブジェクト</param>
/// <returns>キー:プロパティ名、値:プロパティ値(文字列)</returns>
public static Dictionary<string, string> ObjectToDictionary<T>(T data)
{
// 結果格納用の辞書
var dict = new Dictionary<string, string>();
if (data == null) return dict;
// 型情報を取得
Type type = typeof(T);
// すべてのパブリックなインスタンスプロパティを取得
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var prop in properties)
{
// プロパティの値を取得
object value = prop.GetValue(data);
// 値がnullの場合は空文字、それ以外はToString()で文字列化
// 辞書のキーにはプロパティ名を使用
dict[prop.Name] = value?.ToString() ?? string.Empty;
}
return dict;
}
}
実行結果
--- スペック一覧 ---
Model : Alienware X15
Cpu : Core i9-12900H
RamGB : 32
SsdTB : 1
IsLaptop : True
解説と技術的なポイント
1. GetProperties メソッド
typeof(T).GetProperties() を呼び出すことで、その型が持つパブリックプロパティの一覧(PropertyInfo の配列)を取得できます。これにより、どのようなプロパティを持っているか分からないオブジェクトでも動的に処理が可能です。
2. GetValue メソッド
取得した PropertyInfo の GetValue(obj) メソッドを使用することで、具体的なインスタンスからそのプロパティの実際の値を取り出せます。
3. 用途と応用
このテクニックは以下のような場面で非常に役立ちます。
- HTTPリクエスト: オブジェクトを
FormUrlEncodedContentのペアに変換する。 - ログ出力: 構造化ログのためにオブジェクトをフラットなキーバリューに分解する。
- 設定ファイル: クラスの設定値をファイルに書き出す前の形式変換。
値を文字列にせず元の型のまま扱いたい場合は、戻り値を Dictionary<string, object> に変更することで対応可能です。
