我们目前正在实现某种基于字符串的“可扩展枚举类”。下面只显示了此C#代码的一部分,以使问题更易于理解。
如果我运行下面的代码,它会将“BaseValue1”和“BaseValue2”写入控制台。
如果我取消注释 RunClassConstructor 行并运行代码,它还会将“DerivedValue1”和“DerivedValue2”写入控制台。
这就是我想要实现的目标,但我想实现 RunClassConstructor 行。
我认为 DerivedEnum.AllKeys 会触发“DerivedValue1”和“DerivedValue2”的创建,但显然情况并非如此。
是否有可能实现我想要的目标,而不是强迫这些“枚举类”的用户编写一些魔术代码,或者进行某种虚拟初始化?
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
static void Main()
{
//System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DerivedEnum).TypeHandle);
foreach (var value in DerivedEnum.AllKeys)
{
Console.WriteLine(value);
}
}
}
public class BaseEnum
{
private static readonly IDictionary<string, BaseEnum> _dictionary = new Dictionary<string, BaseEnum>();
public static ICollection<string> AllKeys
{
get
{
return _dictionary.Keys;
}
}
public static readonly BaseEnum BaseValue1 = new BaseEnum("BaseValue1");
public static readonly BaseEnum BaseValue2 = new BaseEnum("BaseValue2");
protected BaseEnum(string value)
{
_dictionary[value] = this;
}
}
public class DerivedEnum : BaseEnum
{
public static readonly DerivedEnum DerivedValue1 = new DerivedEnum("DerivedValue1");
public static readonly DerivedEnum DerivedValue2 = new DerivedEnum("DerivedValue2");
protected DerivedEnum(string value)
: base(value)
{
}
}
}
答案 0 :(得分:2)
只有在首次访问类时才会调用静态构造函数。
虽然您使用了DerivedEnum.AllKeys
,但它只是从BaseEnum
继承而来。因此永远不会直接引用DerivedEnum
。
你可以做的一点是实际上在new static
上创建一个DerivedEnum
属性,该属性从基类返回相同的属性,因此在调用它时,将调用派生类的静态构造函数
public class DerivedEnum : BaseEnum
{
public new static ICollection<string> AllKeys
{
get
{
return BaseEnum.AllKeys;
}
}
}
<强>更新强>
您还可以使用System.Reflexion
动态调用它们:
public class BaseEnum
static BaseEnum()
{
// from the types defined in current assembly
Assembly.GetExecutingAssembly().DefinedTypes
// for those who are BaseEnum or its derived
.Where(x => typeof(BaseEnum).IsAssignableFrom(x))
// invoke their static ctor
.ToList().ForEach(x => System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(x.TypeHandle));
}
}
您还可以使用此代码初始化其他程序集中定义的派生类:
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.DefinedTypes)
.Where(x => typeof(BaseEnum).IsAssignableFrom(x))
.ToList().ForEach(x => System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(x.TypeHandle));
答案 1 :(得分:1)
在C#中,静态成员在第一次使用类之前初始化。在您的示例中,您实际上正在使用基类BaseEnum
的成员并绕过DerivedEnum
,这只会导致BaseEnum
的静态成员被初始化。
您需要在派生类中实现AllKeys
属性。这将确保编译器在派生类和&amp;中使用该属性。初始化所有成员。
然后在DerivedEnum中添加新的AllKeys
属性,以覆盖AllKeys
的{{1}}。
BaseEnum