0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

リフレクションを利用した初期化処理を共通にしたい

Last updated at Posted at 2018-11-04

動機

DBのテーブル用にクラスをデザインしたらDDLなどを自動生成するようにしたかった

できたもの

    public abstract class BaseClass
    {
        //派生クラスのプロパティの中身を格納するDictionary
        protected static Dictionary<Type, string> dic = new Dictionary<Type, string>();

        //staticコンストラクタ
        static BaseClass()
        {
            //サブクラスをまとめて初期化
            var subClasses = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes()).Where(t => t.IsSubclassOf(typeof(BaseClass)));

            foreach(var t in subClasses)
            {
                //リフレクションを利用した共通の初期化処理
                dic.Add(t, t.Name);
            }

        }

        //本当はここに書きたい
        //public static string Name { get { return dic["ここの引数が見つからない"]; } }

    }

    public class ClassA : BaseClass
    {
        //ここに書きたくない
        public static string Name { get { return dic[System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType]; } }
    }

    public class ClassB : ClassA
    {
        //多重継承するとnewが必要になる
        public new static string Name { get { return dic[System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType]; } }
    }

感想

うまく行かなくて悲しい

追記

下のような場合、コンパイルすると自動でB.GetInt()はA.GetInt()に変換されるらしい。
参考→stackoverflow
詰んでた(´・ω・`)

class A
{
  public static int GetInt(){}

}
class B : A {}

とりあえず

上のstackoverflowの質問にも幾つか興味深い回答があったけど、それぞれ欠点があったので見送り
派生クラスを綺麗にするために、プロパティという形を諦める

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Namespace
{

    public abstract class BaseClass
    {
        //共通プロパティの中身を格納するDictionary
        public static Dictionary<Type, string> dic = new Dictionary<Type, string>();

        //staticコンストラクタ
        static BaseClass()
        {
            //サブクラスをまとめて初期化
            var subClasses = Assembly.GetAssembly(typeof(BaseClass)).GetTypes().Where(t => t.IsSubclassOf(typeof(BaseClass)));

            foreach (var t in subClasses)
            {
                //リフレクションを利用した何らかの処理の代わり
                var value = t.Name + "ですよ";

                //格納
                dic.Add(t, value);
            }

        }

        public static string GetName<T>() where T : BaseClass
        {
            if (typeof(T) == typeof(BaseClass)) { throw new ArgumentException("BaseClassは入れないで"); }
            return dic[typeof(T)];
        }
    }

    public class ClassA : BaseClass
    {
        //派生クラスは綺麗にできた(`・ω・´)
    }

    public class ClassB : ClassA
    {
        //派生クラスは綺麗にできた(`・ω・´)
    }

    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            System.Diagnostics.Debug.WriteLine(BaseClass.GetName<ClassA>());//ClassAですよ
            System.Diagnostics.Debug.WriteLine(BaseClass.GetName<ClassB>());//ClassBですよ
            System.Diagnostics.Debug.WriteLine(BaseClass.GetName<BaseClass>());//ArgumentException(´・ω・`)
        }
    }
}

0
1
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?