動機
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(´・ω・`)
}
}
}