Dynamically Emitting an Enumerated Type at Runtime
Posted on 7/3/2007
A co-worker asked me the other day if there were a way to build an enumerated type dynamically at runtime. He had an interesting problem. He wanted to be able to read a database table at startup and create an enumerated type from one of the columns in the result. Here's one way to do that. I wrote a helper method called CreateEnumType which you can adapt to your needs.
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
public class EmitAndUseEnumeratedType
{
public static Type CreateEnumType( string enumName,
params string[] literalNames )
{
// create a dynamic module to emit the new type
AppDomain domain = Thread.GetDomain();
AssemblyName name = new AssemblyName(
String.Format( "EnumAssembly_{0}", enumName ) );
AssemblyBuilder asmBuilder = domain.DefineDynamicAssembly(
name, AssemblyBuilderAccess.Run );
ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule(
String.Format( "EnumModule_{0}", enumName ) );
// define the new type and populate it with literal names
EnumBuilder enumBuilder = modBuilder.DefineEnum(
enumName, TypeAttributes.Public, typeof( int ) );
for (int ndx = 0; ndx < literalNames.Length; ndx++)
enumBuilder.DefineLiteral( literalNames[ndx], ndx );
// create the type and return it
Type enumType = enumBuilder.CreateType();
return enumType;
}
public static void Main()
{
// create a new enumerated type called Colors and fill it
Type colorType = CreateEnumType( "Colors", "red", "orange",
"yellow", "green", "blue", "indigo", "violet" );
// create a "blue" one
Enum blueOne = (Enum)Enum.Parse( colorType, "blue" );
// write the enum's value to the console
Console.WriteLine( blueOne );
// get all of the available colors and values
Enum[] allColors = (Enum[])Enum.GetValues( colorType );
int[] allColorValues = (int[])Enum.GetValues( colorType );
// enumerate the enumeration :)
for (int ndx = 0; ndx < allColors.Length; ndx++)
{
Console.WriteLine( "Color '{0}' has the value {1}.",
allColors.GetValue( ndx ), allColorValues[ndx] );
}
}
}
Admittedly, one of the short-comings of this code is that the enumeration that's created only contains sequential integer values starting at zero. Enumerations are not restricted in that way. An enhancement might be to pass corresponding key values from the database to the EnumBuilder's DefineLiteral method. This will create an enumerated type that's somewhat like a dictionary.