Skip to content

rutkowskit/VRT.Generators.EnumToClass

Repository files navigation

EnumToClass Generatror

Enum to class generator generates smart enum class containing constant strings equivalent to enum names. The class decorated with EnumToClassAttribute becomes closed type with private constructor and readonly properties.

Attribute declaration

/// <summary>
/// Generates const string values for each enum field.
/// Makes class/record decorated with the attribute a closed type.
/// </summary>
/// <typeparam name="T">Enum type parameter</typeparam>
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = false)]
[global::System.Diagnostics.Conditional("ENUM_TO_CLASS_GENERATOR_ATTRIBUTES")]
internal sealed class EnumToClassAttribute<T> : global::System.Attribute
    where T : global::System.Enum
{
    public bool WithDescription { get; set; }
}

Optional properties

  1. WithDescription - when set to true it will generate a Description property. The value of this property will be set to: a. DescriptionAttribute if it is present for the enum field a. Documentation comment Summary if it is present for the enum field a. String representation of the enum value

Usage

namespace EnumToClass.Tests.Integration;

public enum TestElements
{
    None,
    Element1,
    Element2,
    Element3
}

[EnumToClass<TestElements>]
internal sealed partial class TestElementClass
{
}

[EnumToClass<TestElements>]
public sealed partial record TestElementRecord
{
}

The default element of the enum will be generated with flag IsEmpty set to true.

The generator will emit the following partial classes:

TestElementClass_Constants.g.cs:

//<auto-generated />     
using System.Collections.Generic;
using System.Collections.ObjectModel;
#nullable enable

namespace EnumToClass.Tests.Integration
{
    internal partial class TestElementClass            
    {
        private static readonly ReadOnlyDictionary<string, TestElementClass> ValueByNameMap = new ReadOnlyDictionary<string, TestElementClass>(new Dictionary<string, TestElementClass>()
        {
            ["None"] = new TestElementClass(EnumToClass.Tests.Integration.TestElements.None),
            ["Element1"] = new TestElementClass(EnumToClass.Tests.Integration.TestElements.Element1),
            ["Element2"] = new TestElementClass(EnumToClass.Tests.Integration.TestElements.Element2),
            ["Element3"] = new TestElementClass(EnumToClass.Tests.Integration.TestElements.Element3)
        });                        
        public const string None = "None";
        public const string Element1 = "Element1";
        public const string Element2 = "Element2";
        public const string Element3 = "Element3";
    }
}

and TestElementClass_Constructors.g.cs:

//<auto-generated />                        
using System.Collections.Generic;
#nullable enable
namespace EnumToClass.Tests.Integration
{
    internal partial class TestElementClass            
    {                    
        private TestElementClass(Integration.TestElements value)
        {
            Name = value.ToString();
            IsEmpty = value == default(Integration.TestElements);
            Value = value;
        }
        public string Name { get; }
        public Integration.TestElements Value { get; }
        public bool IsEmpty { get; }                            

        public static TestElementClass Empty { get; } = new TestElementClass(default(Integration.TestElements));
        public override string ToString() => Name;
        
                public override bool Equals(object? obj)
        {
            return obj is TestElementClass element
                ? element.Value == Value
                : base.Equals(obj);
        }
        public override int GetHashCode() => Value.GetHashCode();
       
        public static IReadOnlyCollection<TestElementClass> GetAll() => ValueByNameMap.Values;
            
        public static IEnumerable<TestElementClass> GetByName(IEnumerable<string> names)
            => names.Select(GetByName).Where(p => p.IsEmpty == false);

        public static TestElementClass GetByName(string name)
        {
            return ValueByNameMap.TryGetValue(name, out var value)
                ? value
                : Empty;
        }
        public static implicit operator TestElementClass(string name) => GetByName(name);
        public static implicit operator string(TestElementClass value) => value.Name;
        public static implicit operator Integration.TestElements(TestElementClass value) => value.Value;
        public static implicit operator TestElementClass(Integration.TestElements value) => GetByName(value.ToString());
        public static implicit operator int(TestElementClass value) => (int) value.Value;
    }
}

Change Log

Version 1.0.6

  1. Add optional description property generation

Version 1.0.5

  1. Add documentation comments based on DescriptionAttribute value.
  2. Fix full enum type name for external enums.
  3. Fix documentation comments for external enums.

Version 1.0.4

  1. Add documentation comments to generated const values based on documentation comments for the enum element

Version 1.0.3

  1. Fix method names in generator.
  2. Replace reflection generated to generator generated values dictionary.
  3. Add GetAll() static function to the class with EnumToClassAttribute attribute.
  4. Add implicit operator to convert enum type value to underlying enum type.

About

Enum to Class code generator

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages