C# 是否可以在类的部分声明中运行多个静态初始值设定项或类似项?
我们的控制系统有很多具有特定版本的数据文件。数据文件是“仅附加的”,因此更高版本将始终包含早期版本中定义的超集 为了避免代码中出现“幻数”,我们创建了一个代码生成器,它接收一段数据并将其转换为C#class文件。我有一个相当大的类库,其中几乎只包含这样的文件。这将导致更可读的代码和一些额外的编译器检查,因为以前有风险的类型转换现在可以成为生成代码的一部分,因此库的用户可以直接使用正确的子类型 然而,问题是最新版本的类库中使用了什么数据文件版本。我希望每个类文件“贡献”到一个全局列表中。如果静态构造函数自动运行,我会这样做:C# 是否可以在类的部分声明中运行多个静态初始值设定项或类似项?,c#,c#-4.0,C#,C# 4.0,我们的控制系统有很多具有特定版本的数据文件。数据文件是“仅附加的”,因此更高版本将始终包含早期版本中定义的超集 为了避免代码中出现“幻数”,我们创建了一个代码生成器,它接收一段数据并将其转换为C#class文件。我有一个相当大的类库,其中几乎只包含这样的文件。这将导致更可读的代码和一些额外的编译器检查,因为以前有风险的类型转换现在可以成为生成代码的一部分,因此库的用户可以直接使用正确的子类型 然而,问题是最新版本的类库中使用了什么数据文件版本。我希望每个类文件“贡献”到一个全局列表中。如果静态构
// GlobalConstants.cs (not generated)
public static partial class GlobalConstants
{
public static List<string> Lst = new List<string>();
static void AddVersionInfo(string mod)
{
Lst.Add(mod);
}
}
// Motor.cs
public static partial class GlobalConstants
{
// Generated from Motor metadata
public class MotorUtil
{
public const int SomeConst1 = 2;
static MotorUtil()
{
AddVersionInfo("<Motor version info>");
}
}
}
// Tank.cs
public static partial class GlobalConstants
{
// Generated from Tank metadata
public class TankUtil
{
public const int SomeConst1 = 2;
public const int SomeConst2 = 3;
public const int SomeConst3 = 5;
static TankUtil()
{
AddVersionInfo("<Tank version info>");
}
}
}
//GlobalConstants.cs(未生成)
公共静态局部类全局常量
{
公共静态列表Lst=新列表();
静态void AddVersionInfo(字符串模式)
{
第一次添加(mod);
}
}
//电机控制系统
公共静态局部类全局常量
{
//从马达元数据生成
公共类MotorUtil
{
公共常数int SomeConst1=2;
静态MotorUtil()
{
AddVersionInfo(“”);
}
}
}
//坦克
公共静态局部类全局常量
{
//从储罐元数据生成
公共类TankUtil
{
公共常数int SomeConst1=2;
公共常数int SomeConst2=3;
公共常数int SomeConst3=5;
静态TankUtil()
{
AddVersionInfo(“”);
}
}
}
如果静态构造函数自动运行,这将导致每个生成的文件(tank.cs、motor.cs、boiler.cs等)被添加到列表中,可以通过工具进行检查
编译时MEF,如果您愿意的话
不幸的是。如果我打印出“Lst”的内容,那么它总是一个空列表,因为静态构造函数还没有运行
这些.cs文件来自不同的方面,不应要求GlobalConstants.cs的作者了解它们。
我的问题是:是否有一种方法可以生成此代码,以便可以随意添加生成的.cs文件,并将它们显示在“Lst”列表中?在第一次引用这些嵌套类之前,每个嵌套类的静态构造函数都不会运行。上述代码中没有出现这种情况,因此列表为空 我可以想象,您可能能够这样做的一种方式是,
GlobalConstants
类中的静态初始值设定项使用反射来查找嵌套类
或者,您可以在引用嵌套类的每个分部类文件中添加一个静态字段,强制其静态构造函数运行:
public static partial class GlobalConstants
{
// Generated from Tank metadata
private static TankUtil _unusedTankUtilField = new TankUtil();
public class TankUtil
{
public const int SomeConst1 = 2;
public const int SomeConst2 = 3;
public const int SomeConst3 = 5;
static TankUtil()
{
AddVersionInfo("<Tank version info>");
}
}
}
公共静态局部类GlobalConstants
{
//从储罐元数据生成
私有静态TankUtil_unusedTankUtilField=new TankUtil();
公共类TankUtil
{
公共常数int SomeConst1=2;
公共常数int SomeConst2=3;
公共常数int SomeConst3=5;
静态TankUtil()
{
AddVersionInfo(“”);
}
}
}
另外,我不认为静态初始化器在部分类文件中的执行顺序是严格定义的(可能与编译器处理它们的顺序相对应)。因此,我建议您让“AddVersionInfo”方法负责初始化列表:
public static partial class GlobalConstants
{
public static List<string> Lst;
static void AddVersionInfo(string mod)
{
if (Lst == null) Lst = new List<string>();
Lst.Add(mod);
}
}
公共静态局部类GlobalConstants
{
公共静态列表Lst;
静态void AddVersionInfo(字符串模式)
{
如果(Lst==null)Lst=newlist();
第一次添加(mod);
}
}
在第一次引用这些嵌套类之前,每个嵌套类的静态构造函数都不会运行。上述代码中没有出现这种情况,因此列表为空
我可以想象,您可能能够这样做的一种方式是,GlobalConstants
类中的静态初始值设定项使用反射来查找嵌套类
或者,您可以在引用嵌套类的每个分部类文件中添加一个静态字段,强制其静态构造函数运行:
public static partial class GlobalConstants
{
// Generated from Tank metadata
private static TankUtil _unusedTankUtilField = new TankUtil();
public class TankUtil
{
public const int SomeConst1 = 2;
public const int SomeConst2 = 3;
public const int SomeConst3 = 5;
static TankUtil()
{
AddVersionInfo("<Tank version info>");
}
}
}
公共静态局部类GlobalConstants
{
//从储罐元数据生成
私有静态TankUtil_unusedTankUtilField=new TankUtil();
公共类TankUtil
{
公共常数int SomeConst1=2;
公共常数int SomeConst2=3;
公共常数int SomeConst3=5;
静态TankUtil()
{
AddVersionInfo(“”);
}
}
}
另外,我不认为静态初始化器在部分类文件中的执行顺序是严格定义的(可能与编译器处理它们的顺序相对应)。因此,我建议您让“AddVersionInfo”方法负责初始化列表:
public static partial class GlobalConstants
{
public static List<string> Lst;
static void AddVersionInfo(string mod)
{
if (Lst == null) Lst = new List<string>();
Lst.Add(mod);
}
}
公共静态局部类GlobalConstants
{
公共静态列表Lst;
静态void AddVersionInfo(字符串模式)
{
如果(Lst==null)Lst=newlist();
第一次添加(mod);
}
}
对于更简单的语法,可以使用属性而不是静态类
如果您定义了一个属性
public class UtilVersionAttribute : Attribute
{
private readonly string _versionInfo;
public UtilVersionAttribute(string versionInfo) { _versionInfo = versionInfo; }
public string VersionInfo { get { return _versionInfo; } }
}
…您可以将这些类改为属性
public static partial class GlobalConstants
{
[UtilVersion("<Motor version info>")]
public class MotorUtil
{
public const int SomeConst1 = 2;
}
}
…以获取您的版本的完整列表
MEF也可能有帮助,你可能想考虑使用它,而不是实施一个“轻版本”。即使您的静态构造函数注册是运行时注册,而不是编译时注册,所以我不确定您不使用它的原因。
对于更简单的语法,您可以使用属性而不是静态类 如果您定义了一个属性public class UtilVersionAttribute : Attribute
{
private readonly string _versionInfo;
public UtilVersionAttribute(string versionInfo) { _versionInfo = versionInfo; }
public string VersionInfo { get { return _versionInfo; } }
}
…你