Apologies for the late reply when I promised earlier.
The idea I have involves using a runtime code compiler, as well as reflection to dynamically create a class containing all of these constants.
So, the steps (or pseudo codes), as I see it, are as follows:
- For each .h file, read all lines starting with
#define and save them. - Using
Microsoft.CSharp.CSharpCodeProvider() and an empty template file, compile the DLL in memory, which contains a class that provides style constants public const int ALPHA_REACTOR_CODE = 99641; . - Use
Assembly.GetType(string) to get the type of the generated class - Use Reflection and a method that takes a constant name to access a value.
So, if this is our attack plan, here are some pieces of code that can help you.
1. Downloading .h files This is a fairly simple file reading, the key trick is to filter your lines by #define and then parse them into Dictionary<string, int> .
lines.Where(line => line.StartsWith("#define", true, CultureInfo.CurrentCulture)) .Select(line => line.Split(' ').Skip(1)) .ToDictionary(lineParts => lineParts.First(), lineParts => int.Parse(lineParts.Last()));
This will create a dictionary of all your definitions. You can call .Distict() to .ToDictionary() only if duplicate definitions exist.
2. Create an assembly Here you use Microsoft.CSharp.CSharpCodeProvider() to create an assembly in memory. The trick here is to have a GenerateCode.cs file that contains the base structure for the class. This must be set as EmbeddedResource, otherwise it will try and be compiled (which will not work).
using System; namespace GeneratedCode {{ public class GeneratedConstants {{ {0} }} }}
You will notice {0} , we use this with string.Format to insert constants into the file.
Use assembly.GetManifestResourceStream() to get the stream of this template file and a regular StreamReader to read it into one large line in memory.
Generate constants using StringBuilder and basic string.Format() formatting in combination with the Value Dictionary.
StringBuilder builder = new StringBuilder(); foreach (var constant in dict) { builder.AppendFormat(CultureInfo.CurrentCulture, "public const int {0} = {1};", constant.Key, constant.Value); }
Then just use string.Format () to insert the builder string into the string of the generated class (using {0} )
Then you just need to use Microsoft.CSharp.CSharpCodeProvider() to assemble the assembly in memory.
using (CSharpCodeProvider provider = new CSharpCodeProvider()) { parameters.ReferencedAssemblies.Add("System.dll"); parameters.ReferencedAssemblies.Add("System.Core.dll"); CompilerResults results = provider.CompileAssemblyFromSource(parameters, sourceCode); }
3 and 4. Using Reflection now you have an assembly containing a type with constants defined in it, you can use assembly.GetType("GeneratedCode.GeneratedConstants"); to get the type and use Reflection to get the constants one at a time or all together.
Have a look at this blog post which tells how to get const using reflection: http://weblogs.asp.net/whaggard/archive/2003/02/20/2708.aspx
Ok, hope this helps you. This is not a difficult decision, but has several moving parts.
Good luck