Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以在类的部分声明中运行多个静态初始值设定项或类似项?_C#_C# 4.0 - Fatal编程技术网

C# 是否可以在类的部分声明中运行多个静态初始值设定项或类似项?

C# 是否可以在类的部分声明中运行多个静态初始值设定项或类似项?,c#,c#-4.0,C#,C# 4.0,我们的控制系统有很多具有特定版本的数据文件。数据文件是“仅附加的”,因此更高版本将始终包含早期版本中定义的超集 为了避免代码中出现“幻数”,我们创建了一个代码生成器,它接收一段数据并将其转换为C#class文件。我有一个相当大的类库,其中几乎只包含这样的文件。这将导致更可读的代码和一些额外的编译器检查,因为以前有风险的类型转换现在可以成为生成代码的一部分,因此库的用户可以直接使用正确的子类型 然而,问题是最新版本的类库中使用了什么数据文件版本。我希望每个类文件“贡献”到一个全局列表中。如果静态构

我们的控制系统有很多具有特定版本的数据文件。数据文件是“仅附加的”,因此更高版本将始终包含早期版本中定义的超集

为了避免代码中出现“幻数”,我们创建了一个代码生成器,它接收一段数据并将其转换为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; } }
}
…你