【C#】プロパティを動的に検索して型の種類を取得する!

みなさんこんにちは!ひろぽんです!

さて今回はClassのプロパティを動的に検索して型の種類を取得するプログラムを書いていきたいと思います!

めちゃくちゃ簡単なので、ぜひこの機会に覚えてください

さてそれでは本題!!

目次

Type.GetProperties関数でとれる

💡 プロパティ vs フィールドの違いは別記事 プロパティとフィールドの違い で書いてます。

結論から言うとType型が持っているGetProperties関数を実行すればPropertyInfoの配列が返ってきて、PropertyInfoの中に型が入っています。

ではサンプルを書いていきましょう!

まずはサンプルクラスの用意

まずは下記のようなCarというサンプルクラスを用意します!

    public class Car
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Maker { get; set; }

    public Car(int id, string name, string maker)
    {
        ID = id;
        Name = name;
        Maker = maker;
    }

    public Car()
    {
        
    }
}</code></pre></div>

Propertyの配列を取得する

で上記クラスのPropertyInfoの配列取得します。

PropertyInfoから型を取得する

下記のコードでCarクラスのプロパティの一覧を取得できます。

            PropertyInfo[] props = typeof(Car).GetProperties();

で上記で取得したPropertyInfoの配列をぶん回して下記のコードで中身を見てみるとこんな感じ!

    class Program
    {
        static void Main(string[] args)
        {
            PropertyInfo[] props = typeof(Car).GetProperties();

        foreach (PropertyInfo prop in props)
        {
            Console.WriteLine($@&quot;{prop.Name} : {prop.PropertyType}&quot;);
        }

        Console.ReadLine();
    }
}</code></pre></div>

これをぶん回すと!

ちゃんとデータ型が取れているのが分かりますね!

動的に値を自由に操作することも可能!

実はこの方法を少し応用すれば、プロパティの値を動的に変更することもできます!

いつもなら下記のようなコードを書いてプロパティを変更してるとして。

            var car = new Car(1,"インプレッサ","subaru");
            car.Name = "フォレスター";

下記のようなコードでプロパティを変更できます!

            var car = new Car(1, "インプレッサ", "subaru");
            var carNameProp = props.First(item => item.Name == nameof(Car.Name));
            carNameProp.SetValue(car,"フォレスター");
            Console.WriteLine(car.Name);

ちゃんと変わっていますね!

この手法については下記の記事で詳しく書いていますので、是非ご覧ください!

詳しくは下記の記事を参照ください!

https://hiropon-progra.com/?p=789

今回の記事のサンプルコードをGithubで公開しています!

下記リポジトリで公開しているので、興味のある方はぜひ見てみてください!

GitHub
GitHub - HayashiyamaHiroshi/blog-source-demo Contribute to HayashiyamaHiroshi/blog-source-demo development by creating an account on GitHub.

💡 補足: 業務系の現場でよくハマるパターン

俺もこのリフレクション + プロパティ列挙、 業務でハマってきたところを3つ並べておきます。

① ループ内の GetProperties で性能死亡

foreach 内で毎回 typeof(T).GetProperties() 呼ぶと、 型情報を毎回構築。 1万行で 10倍遅い。 静的キャッシュ or Lazy<T> で1回だけ取得が定石。

② BindingFlags 指定漏れで private が取れない

デフォルトの GetProperties() は public のみ。 private/protected 含めるには BindingFlags.NonPublic | BindingFlags.Instance を指定。 半日デバッガで「なぜ取れない」と追ってから判明する罠。

③ SetValue で値型キャスト失敗

PropertyInfo.SetValue(obj, "123") で string → int 暗黙変換は走らない。 Convert.ChangeType 噛ます or 明示キャスト必須。 DataRow からの動的セットでハマる頻出パターン。

❓ よくある質問

Q1. GetProperties() のパフォーマンス改善方法は?

A. (1) ループ外でキャッシュ、 (2) ConcurrentDictionary<Type, PropertyInfo[]> で型ごと記憶、 (3) .NET 6+ なら Source Generator 検討。 (1) だけで 5-10倍速くなる。

Q2. プロパティだけでなくフィールドも列挙したい

A. typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance) で取得。 業務系では「データクラス全項目を loop」の用途で必要になることが多い。

Q3. 動的にプロパティ設定する API デザインは?

A. SetProperty<T>(object obj, string name, T value) のジェネリックメソッドで型安全に。 SetValue 直叩きより安全。

Q4. PropertyInfo.GetValue() のキャストは?

A. 戻り値は object なので (int)pi.GetValue(obj)。 null 可能性ある場合は (int?)pi.GetValue(obj) ?? 0

Q5. リフレクションを業務系で使う場面は?

A. DTO → DataTable 変換、 設定ファイル → クラスマッピング、 動的 SQL 生成等。 性能要求がない箇所のみ。 hot path では避ける。

📚 関連記事

この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次