Generating Enum Descriptions using ISourceGenerator

I'm a big fan of enums in C# and tend to use enums often. I typically use them for anything with a limited set of possible options, such as days of the week, the status of an order etc.

There are several benefits to using enums namely:

  • Reduces errors caused by transposing or mistyping numbers.

  • Makes it easy to change values in the future.

  • Makes code easier to read, which means it is less likely that errors will creep into it.

  • Ensures forward compatibility. With enumerations, your code is less likely to fail if in the future someone changes the values corresponding to the member names.

Having said that, if you take the code below, without creating an extension, it's not easy to return a friendly description of the enum. Even though we defined friendly descriptions for each of our enumeration elements, using the normal ToString() method will keep printing non-friendly names.


public enum CurrenyTypeFilter
{
   [Description("None")]
   None = 0,
   [Description("United States Dollar")]
   USD = 1,
   [Description("Pound Sterling")]
   GBP = 2,
   [Description("Euro")]
   EUR = 3

}

So, printing the descriptive friendly names that we defined requires an extension method. Traditionally, I have done this by writing an extension method, as shown below.


public static class EnumExtensionMethods
    {
        public static string GetDescription(this Enum GenericEnum)
        {
            Type genericEnumType = GenericEnum.GetType();
            MemberInfo[] memberInfo = genericEnumType.GetMember(GenericEnum.ToString());
            if ((memberInfo != null && memberInfo.Length > 0))
            {
                var _Attribs = memberInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false);
                if ((_Attribs != null && _Attribs.Count() > 0))
                {
                    return ((System.ComponentModel.DescriptionAttribute)_Attribs.ElementAt(0)).Description;
                }
            }
            return GenericEnum.ToString();
        }

    }

The downside of this though is that this would apply the GetDescription() to every Enum in your project. That's why I wrote an Enum to String Source Generator, leveraging C# Source Generators.


For the impatient: TL;DR

The GitHub Project is at the bottom of the page


The source generator generates a GetDescription method for enumerations that have the [GenerateEnumDescription] defined. Add a reference in your project to the EnumDescriptorGenerator project and then set OutputItemType="Analyzer" and ReferenceOutputAssembly="false" as shown below.


<ItemGroup>
  <ProjectReference Include="..\..\src\EnumDescriptorGenerator\EnumDescriptorGenerator.csproj"
					OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>

All enum's with the [GenerateEnumDescription] will now be selected to be processed by the Source Generator.

[GenerateEnumDescription]
public enum CurrenyTypeFilter
{
   [Description("None")]
   None = 0,
   [Description("United States Dollar")]
   USD = 1,
   .....

}

You can customize the enum value using the [Description("First Test Enum")] attribute. If none is set nameof(EnumExample.TestEnum.SecondTestEnum) will be returned.

To test the output, you can simply call GetDescription().


CurrenyTypeFilter.USD.GetDescription();

Which would then return United States Dollar.

The sample code is available at Netizine/EnumDescriptorGenerator (github.com)