Our control system has a lot of data files that have specific versions. The data files are “append only”, so a higher version will always contain a superset of the definitions in the earlier versions.
In order to avoid “magic numbers” in our code, we have created a code generator that take a piece of data and turns it into a C# class file. I have a pretty large class library containing pretty much only such files. This results in much more readable code and some additional compiler checks because type previously risky type casting can now be part of the generated code, so that users of the library consume their correct subtypes directly.
However, the question comes up what data file version was used in the latest version of the class library. I would like every class file to “contribute” to a global list. If static constructors were automatically run, this is what I would do:
// 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>");
}
}
}
If static constructors where run automatically, this would result in every generated file (tank.cs, motor.cs, boiler.cs etc) being added to the list, which could be inspected by a tool.
A compile time MEF, if you like.
Unfortunately. If I print out contents of “Lst”, then it’s always an empty list because the static constructors haven’t run.
These .cs files come from different parties and the author of GlobalConstants.cs should not be required to know about them.
My question is: Is there a way in which I can generate this code so that one can add generated .cs files at will and they will appear in the “Lst” list?
The static constructors for each of your nested classes won’t run until those nested classes are referenced for the first time. That hasn’t happened in your above code, hence the list is empty.
One way I could imagine you might be able to do this would be for a static initializer in the
GlobalConstantsclass to use reflection to find the nested classes.Or maybe you could add a static field in each partial class file that references the nested class, forcing its static constructor to run:
Also I don’t believe the order of execution of static initializers across partial class files is strictly defined (presumably corresponds to the order they are processed by the compiler). So I’d suggest you make your “AddVersionInfo” method responsible for initializing the list: