C#にて文字列でプロパティ名を指定して、インスタンスから値を取得する方法

2019年11月15日

リフレクションを使用してインスタンスからプロパティ名を文字列で指定して値を取得したり、設定したりするメソッドを書きました。
あまりリフレクションを使いたくなかったのですが、業務上、他社が作ったモジュールをプラグインで使用するためにインポートして・・・
みたいながあると思います。今回はそんな感じでやむなく。
なぜやむなくかと言うと、リフレクションは可読性も実行速度も下がり実行時エラーの要因になるから。
可能であるなら使う前に配列やDictionary等でうまく対応する方法を検討すべきだと考えてます。

値を取得するメソッドはこれ

        /// <summary>
        /// リフレクションを使用して対象インスタンスから指定されたプロパティ名の値を取得
        /// </summary>
        /// <typeparam name="T">取得対象となるクラスの型</typeparam>
        /// <param name="instance">取得対象となるクラスのインスタンス</param>
        /// <param name="colName">プロパティ名</param>
        /// <returns></returns>
        private static object GetValueByPropertyName<T>(T instance, string colName)
        {
            if (instance == null) return null;
            var property = typeof(T).GetProperty(colName);
            var val = property?.GetValue(instance);
            return val;
        }

値を設定するメソッドはこれ

        /// <summary>
        /// リフレクションを使用して対象インスタンスから指定されたプロパティ名の値を取得
        /// </summary>
        /// <typeparam name="T">取得対象となるクラスの型</typeparam>
        /// <typeparam name="TSet">設定する値の型</typeparam>
        /// <param name="instance">取得対象となるクラスのインスタンス</param>
        /// <param name="colName">プロパティ名</param>
        /// <param name="setValue"></param>
        /// <returns></returns>
        private static void SetValueByPropertyName<T, TSet>(T instance, string colName, TSet setValue)
            where T : class
        {
            if (instance == null) return;
            var property = typeof(T).GetProperty(colName);
            if (property != null && property.PropertyType == typeof(TSet))
            {
                property.SetValue(instance, setValue);
            }
        }

以下に使用例を載せる。

using System;
using System.Linq;
using System.Diagnostics;
using System.Collections.Generic;

namespace MyTest
{
    internal class Program
    {
        public class Person
        {
            public int ID { get; set; }
            public string LastName { get; set; }
            public string FirstMidName { get; set; }

            public Person(int id, string lastName, string firstMidName)
            {
                this.ID = id;
                this.LastName = lastName;
                this.FirstMidName = firstMidName;
            }
        }
        public static void Main(string[] args)
        {
            Trace.Listeners.Add(new DefaultTraceListener());

            List<Person> students = new List<Person>();
            for (int i = 0; i < 5; i++)
            {
                students.Add(new Person(i,$"LastName{i}", $"FirstMidName{i}"));
            }

            var student1 = students[1];

            // 値をプロパティ名で取得
            var targetLastName = GetValueByPropertyName<Person>(student1, "LastName");
            Console.WriteLine(targetLastName);
            // 設定する型がプロパティの型と一致しない場合は代入されない
            SetValueByPropertyName<Person,int>(student1, "LastName",3);
            // 一致する場合は代入される。
            SetValueByPropertyName<Person,string>(student1, "LastName","ChangeName");
        }

        /// <summary>
        /// リフレクションを使用して対象インスタンスから指定されたプロパティ名の値を取得
        /// </summary>
        /// <typeparam name="T">取得対象となるクラスの型</typeparam>
        /// <param name="instance">取得対象となるクラスのインスタンス</param>
        /// <param name="colName">プロパティ名</param>
        /// <returns></returns>
        private static object GetValueByPropertyName<T>(T instance, string colName)
            where T : class
        {
            if (instance == null || colName == null) return null;
            var property = typeof(T).GetProperty(colName);
            var val = property?.GetValue(instance);
            return val;
        }


        /// <summary>
        /// リフレクションを使用して対象インスタンスから指定されたプロパティ名の値を取得
        /// </summary>
        /// <typeparam name="T">取得対象となるクラスの型</typeparam>
        /// <typeparam name="TSet">設定する値の型</typeparam>
        /// <param name="instance">取得対象となるクラスのインスタンス</param>
        /// <param name="colName">プロパティ名</param>
        /// <param name="setValue"></param>
        /// <returns></returns>
        private static void SetValueByPropertyName<T, TSet>(T instance, string colName, TSet setValue)
            where T : class
        {
            if (instance == null || colName == null) return;
            var property = typeof(T).GetProperty(colName);
            if (property != null && property.PropertyType == typeof(TSet))
            {
                property.SetValue(instance, setValue);
            }
        }
    }
}

C#C#

Posted by takumioda