以下のコードを参照してください。独自の型の定義済みのすべての静的読み取り専用インスタンスを自動的に列挙するクラスが必要です (例として TestClass を参照してください。独自の型の 3 つの静的読み取り専用インスタンスを定義しています)。
この自動化が必要なのは、定義された型をループして、 のリストに新しいインスタンスを追加するのを忘れるという変更のリスクを冒したくないからですAll
。
わかりました、私はそれを機能させました、それはポイントではありません。FillAll
しかし、静的コンストラクターから呼び出されたときに機能しないのはなぜですか? DefinedInstancesBase<T>
コード内のコメント化された静的コンストラクターを参照してください。FieldInfo.GetValue(null)
静的コンストラクターで null を返すことを意味しますが、デバッガーFieldInfo.GetValue(null)
は呼び出される前に静的読み取り専用インスタンスの作成に既にヒットしています。
うまくいかない理由がとても気になります。これは設計によるものですか?
public abstract class DefinedInstancesBase<T>
{
public static IList<T> All
{
get
{
if (_All == null)
{
FillAll();
}
return _All;
}
}
//Why this doesn't work? No idea.
//static DefinedInstancesBase()
//{
// FillAll();
//}
private static void FillAll()
{
var typeOfT = typeof(T);
var fields = typeOfT.GetFields(BindingFlags.Public | BindingFlags.Static);
var fieldsOfTypeT = fields.Where(f => f.FieldType == typeOfT);
_All = new List<T>();
foreach (var fieldOfTypeT in fieldsOfTypeT)
{
_All.Add((T)fieldOfTypeT.GetValue(null));
}
}
private static List<T> _All = null;
}
[TestClass]
public class DefinedInstancesTest
{
[TestMethod]
public void StaticReadOnlyInstancesAreEnumerated()
{
//Given
var expectedClasses = new List<TestClass>
{
TestClass.First,
TestClass.Second,
TestClass.Third,
};
//When
var actualClasses = TestClass.All;
//Then
for (var i=0; i<expectedClasses.Count; i++)
{
Assert.AreEqual(expectedClasses[i].Id, actualClasses[i].Id);
}
}
private class TestClass : DefinedInstancesBase<TestClass>
{
public static readonly TestClass First = new TestClass(1);
public static readonly TestClass Second = new TestClass(2);
public static readonly TestClass Third = new TestClass(3);
public int Id { get; private set; }
private TestClass(int pId)
{
Id = pId;
}
}
}