Search code examples
c#system.reflection

C# reflections with enum as string


I have a structure that contains an enum:

public enum MyEnum
{
    happy = 0,
    sad
}

public struct MyStruct
{
    public MyEnum feelings;
    public int boopCounter;
}

and then I am given a text/string version of a structure and its contents:

feelings = sad
boopCounter = 12

I am trying to write a generic parser that can generate a struct object with the correctly populated fields, without having to modify the parser every time the structure gets updated. I have been generally successful using Reflections:

// Scan through each member of the structure, looking for a match
foreach (var field in typeof(MyStruct).GetFields(System.Reflection.BindingFlags.Instance |
                                                 System.Reflection.BindingFlags.NonPublic |
                                                 System.Reflection.BindingFlags.Public))
{
    if(field.Name == fieldNameFromText)
    {
        // This is the member we need to update. Treat enums differently
        var fld = typeof(MyStruct).GetField(field.Name);
        if(field.FieldType.IsEnum)
        {
            //fld.SetValue(s, Enum.ToObject(field.FieldType, valFromText));   // Didn't work

            fld.SetValue(s, Convert.ChangeType(Enum.ToObject(field.FieldType, Convert.ToInt32(valFromText)), field.FieldType)); // Worked, but only if integer version of enum is passed in
        }
        else
        {
            // Not an enum, parse directly.
            fld.SetValue(s, Convert.ChangeType(valFromText, field.FieldType));
        }
        break;
    }
}

So this code works, but it only works if my input text contains the integer version of the enum:

feelings = 1
boopCounter = 12

Is there a way to get this to work with the original string enumeration input ("sad") ? I'd like to keep it generic if possible (notice how my code doesn't ever specifically call out "MyEnum" anywhere).


Solution

  • Yes, you can use the non-generic version of Enum.Parse.

    var fieldType = fld.FieldType;
    if (fieldType.IsEnum)
    {
        var valueToAssign = Enum.Parse(fieldType, valFromText);
        fld.SetValue(s, valueToAssign);
    }