RunningCSharp

MS系開発者による、雑多な記事。記事は所属企業とは関係のない、個人の見解です。

C#:基底クラスのプロパティ情報をリフレクションで取得する拡張メソッド

    /// <summary>
    /// 基底クラス
    /// </summary>
    public class SuperClass
    {
        public SuperClass()
        {
            SuperProperty = "Super";
        }
        private string SuperProperty { get; set; }
    }

    /// <summary>
    /// 派生クラス(子クラス)
    /// </summary>
    public class Sub1Class : SuperClass
    {
    }

    /// <summary>
    /// 派生クラスの派生クラス(孫クラス)
    /// </summary>
    public class Sub2Class : Sub1Class
    {
    }

上記のようなクラス構成で「Sub2Class」より、SuperClassのSuperPropertyを取得したい場合、 privateなプロパティなので、リフレクションを用いて取得することになります。

しかし、孫クラスとなっているため単純にBaseTypeでクラス情報を取得することもできないため、 プロパティ名とBindingFlagsを渡すと継承ツリーからプロパティを取得してくる拡張メソッドを作成してみました。

    public static class MethodClass
    {
        /// <summary>
        /// プロパティ名とBindingFlagsより、型の継承ツリー内にあるプロパティ情報を検索し返却します。
        /// 最も派生クラスに近いクラスのプロパティが返却されます。
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name">プロパティ名</param>
        /// <param name="bindingAttr">BindingFlags</param>
        /// <returns>プロパティを表すオブジェクト</returns>
        public static PropertyInfo GetSuperClassPropertyInfo(this Type type, string name, BindingFlags bindingAttr)
        {
            var info = type.GetProperty(name, bindingAttr);
            if (info != null)
            {
                return info;
            }
            else if (type.BaseType != null)
            {
                return type.BaseType.GetSuperClassPropertyInfo(name, bindingAttr);
            }
            return null;
        }
    }

下記のような形で使用します。

    class Program
    {
        static void Main(string[] args)
        {
            Sub2Class sub2Class = new Sub2Class();
            var info = sub2Class.GetType().GetSuperClassPropertyInfo("SuperProperty", BindingFlags.Instance | BindingFlags.NonPublic);
            Console.WriteLine((string)info.GetValue(sub2Class));
            Console.ReadLine();
        }
    }

実行結果は、

Super

となります。

もう少しスマートな方法があると良いなとは思うのですが…