Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill/update the enum values at runtime in C#

Tags:

c#

enums

dynamic

I have windows app where-in i need to fill enum values at runtime by reading a text file named "Controls.txt". As restriction, i'm not suppose to use dictionary. Below is the default values available in the enum MyControls. I have to use enums only.

public enum MyControls
{
   Button1 = 0,
   Button2 = 1,
   Button3 = 2,
}

If Controls.txt file is available, then content of enum should change like

public enum MyControls
{
   btn1 = 0,
   btn2 = 1,
   btn3 = 2,
}

how do i achieve this. I also came across the link Creating / Modifying Enums at Runtime but could not get idea.

like image 808
sia Avatar asked Dec 04 '14 09:12

sia


People also ask

Can we change enum values in runtime?

No, enums information is erased at compile time.

Can you change the value of an enum in C?

You can change default values of enum elements during declaration (if necessary).

Can we add new enumeration value by runtime?

No, you cannot modify types at runtime. You could emit new types, but modifying existing ones is not possible.

Can enum be updated?

Enum constants are singleton and immutable objects can be used all over the application and mass and radius fields cannot be changed on the fly according to database updates. Instead, in-memory cache can be created to store mass and radius values and this internal Map can be refreshed on every database update.


2 Answers

I strongly think you are trying to solve the wrong problem. The value of enum is type-safety. I do not think that filling it up dynamically is a good idea. What would really be useful is to have an enum populated by a text file (for example) even before compilation. You can do this using text templates in VS.

You can find an example in my blog post here: http://skleanthous.azurewebsites.net/post/2014/05/21/Creating-enums-from-the-database-and-using-them-in-Entity-framework-5-and-later-in-model-first

Although my example loads from a db, changing it to load from a text file should be trivial.

like image 91
Savvas Kleanthous Avatar answered Oct 16 '22 15:10

Savvas Kleanthous


Apart from the fact that i agree with the other answer that says that you lose type and compile time safety, using EnumBuilderClass should be the only way (thanks to huMpty duMpty's comment).

// sample "file":
string fileContent = @"
btn1 = 0,
btn2 = 1,
btn3 = 2,
";
var enumBody = fileContent.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
    .Select(line => new { bothToken = line.Trim().Trim(',').Split('=') })
    .Where(x => x.bothToken.Length == 2)
    .Select(x => new { Name = x.bothToken[0].Trim(), Value = int.Parse(x.bothToken[1].Trim()) });

AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName asmName = new AssemblyName("EnumAssembly");
AssemblyBuilder asmBuilder = currentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = asmBuilder.DefineDynamicModule(asmName.Name, asmName.Name + ".dll");
string enumTypeName = string.Format("{0}.{1}", typeof(MyControls).Namespace, typeof(MyControls).Name);
EnumBuilder eb = mb.DefineEnum(enumTypeName, TypeAttributes.Public, typeof(int));
foreach(var element in enumBody)
{
    FieldBuilder fb1 = eb.DefineLiteral(element.Name, element.Value);
}
Type eType = eb.CreateType();

foreach (object obj in Enum.GetValues(eType))
{
    Console.WriteLine("{0}.{1} = {2}", eType, obj, ((int)obj));
}

Output:

Namespacename.MyControls.btn1 = 0
Namespacename.MyControls.btn2 = 1
Namespacename.MyControls.btn3 = 2
like image 29
Tim Schmelter Avatar answered Oct 16 '22 16:10

Tim Schmelter