Microsoft shows how to create a dynamic class here:
http://msdn.microsoft.com/en-us/library/system.reflection.emit.modulebuilder(v=vs.71).aspx
This defines a custom object, where they define a constructor and a method. I have a class defined, is there a way to emit the class I have already written instead of trying to write it as the example shows?
Thanks FacticiusVir, it's nearly complete. However it doesn't seem to be quite there, 'Countries.USA is not supported by the language'
Full code including FacticiusVir's answer:
class DynamicEnums
{
public static void Main()
{
AppDomain domain = AppDomain.CurrentDomain;
AssemblyName aName = new AssemblyName("DynamicEnums");
AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
ConstructorInfo referenceObjectConstructor = typeof(ReferenceObject).GetConstructor(new[] { typeof(int) });
List<Type> types = new List<Type>();
foreach(ReferenceType rt in GetTypes())
{
TypeBuilder tb = mb.DefineType(rt.Name, TypeAttributes.Public);
ConstructorBuilder staticConstructorBuilder = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
ILGenerator staticConstructorILGenerator = staticConstructorBuilder.GetILGenerator();
foreach (Reference r in GetReferences(rt.ID))
{
string name;
if (rt.Name == "Countries")
name = r.Abbreviation.Trim();
else if (rt.Name == "PermanentFundDividends")
name = "Year" + r.Abbreviation.Trim();
else
name = NameFix(r.Name);
// Create a public, static, readonly field to store the
// named ReferenceObject.
FieldBuilder referenceObjectField = tb.DefineField(name, typeof(ReferenceObject), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.InitOnly);
// Add code to the static constructor to populate the
// ReferenceObject field:
// Load the ReferenceObject's ID value onto the stack as a
// literal 4-byte integer (Int32).
staticConstructorILGenerator.Emit(OpCodes.Ldc_I4, r.ID);
// Create a reference to a new ReferenceObject on the stack
// by calling the ReferenceObject(int32 pValue) reference
// we created earlier.
staticConstructorILGenerator.Emit(OpCodes.Newobj, referenceObjectConstructor);
// Store the ReferenceObject reference to the static
// ReferenceObject field.
staticConstructorILGenerator.Emit(OpCodes.Stsfld, referenceObjectField);
}
staticConstructorILGenerator.Emit(OpCodes.Ret);
types.Add(tb.CreateType());
}
try
{
ab.Save(aName.Name + ".dll");
}
catch (Exception)
{
Console.WriteLine("Could not save .dll, file must already be loaded.");
}
foreach (Type t in types)
{
foreach (FieldInfo o in t.GetFields())
{
Console.WriteLine("{0}.{1} = {2}", t, o.Name, "Later"); //Don't know how to get Value doing it this way
}
Console.WriteLine();
//Console.ReadKey();
}
Console.WriteLine();
Console.WriteLine("Dynamic Enums Built Successfully.");
//Console.ReadKey();
}
public static List<ReferenceType> GetTypes()
{
List<ReferenceType> referenceTypes = new List<ReferenceType>();
referenceTypes.Add(new ReferenceType { ID = 1, Name = "Countries" });
return referenceTypes;
}
public static List<Reference> GetReferences(int typeID)
{
List<Reference> references = new List<Reference>();
references.Add(new Reference { ID = 120, Abbreviation = "USA" });
return references;
}
public struct ReferenceType
{
public int ID;
public string Name;
}
public struct Reference
{
public int ID;
public int TypeID;
public string Abbreviation;
public string Name;
}
public static string NameFix(string name)
{
//Strip all non alphanumeric characters
string r = Regex.Replace(name, @"[^\w]", "");
//Enums cannot begin with a number
if (Regex.IsMatch(r, @"^\d"))
r = "N" + r;
return r;
}
}
public class ReferenceObject
{
private readonly int value;
public ReferenceObject(int pValue)
{
value = pValue;
}
public override string ToString()
{
return value.ToString();
}
public int Value()
{
return value;
}
public int ID()
{
return value;
}
#region == Operator
public static bool operator ==(int objLeft, ReferenceObject objRight)
{
return objLeft == objRight.value;
}
public static bool operator ==(ReferenceObject objLeft, int objRight)
{
return objLeft.value == objRight;
}
public static bool operator ==(string objLeft, ReferenceObject objRight)
{
return objLeft == objRight.value.ToString();
}
public static bool operator ==(ReferenceObject objLeft, string objRight)
{
return objLeft.value.ToString() == objRight;
}
#endregion
#region != Operator
public static bool operator !=(int objLeft, ReferenceObject objRight)
{
return objLeft != objRight.value;
}
public static bool operator !=(ReferenceObject objLeft, int objRight)
{
return objLeft.value != objRight;
}
public static bool operator !=(string objLeft, ReferenceObject objRight)
{
return objLeft != objRight.value.ToString();
}
public static bool operator !=(ReferenceObject objLeft, string objRight)
{
return objLeft.value.ToString() != objRight;
}
#endregion
public override bool Equals(object obj)
{
if ((obj is ReferenceObject))
return value == ((ReferenceObject)obj).value;
if ((obj is int))
return value == (int)obj;
if ((obj is string))
return value.ToString() == (string)obj;
return false;
}
public override int GetHashCode()
{
return value;
}
}