EnumToClass 1.0.8
dotnet add package EnumToClass --version 1.0.8
NuGet\Install-Package EnumToClass -Version 1.0.8
<PackageReference Include="EnumToClass" Version="1.0.8"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="EnumToClass" Version="1.0.8" />
<PackageReference Include="EnumToClass"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add EnumToClass --version 1.0.8
#r "nuget: EnumToClass, 1.0.8"
#:package EnumToClass@1.0.8
#addin nuget:?package=EnumToClass&version=1.0.8
#tool nuget:?package=EnumToClass&version=1.0.8
EnumToClass Generator
C# source generator that turns an enum into a smart-enum style closed class/record: constant string names, flyweight instances, lookup helpers, and conversions.
The type decorated with EnumToClassAttribute<TEnum> becomes a closed type with a private constructor and readonly properties.
Attribute
/// <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
WithDescription— whentrue, generates aDescriptionproperty. Value resolution order:DescriptionAttributeon the enum field, if present- Full text of the XML documentation
<summary>(all lines, newline-separated), if present - The enum member name
Projecting enum-member attributes as properties
Opt-in companion attribute (can be applied multiple times):
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[Conditional("ENUM_TO_CLASS_GENERATOR_ATTRIBUTES")]
internal sealed class EnumToClassPropertyAttribute<TAttribute> : Attribute
where TAttribute : Attribute
{
/// <summary>Generated property name. Default: TAttribute name without "Attribute" suffix.</summary>
public string? Name { get; set; }
/// <summary>
/// When true, property type is an array (all applications on the member; empty array if none).
/// When false (default), first application or null.
/// </summary>
public bool AsArray { get; set; }
/// <summary>
/// When set, project this member of TAttribute (property or ctor parameter) instead of the attribute instance.
/// Single segment only (e.g. "Name").
/// </summary>
public string? Source { get; set; }
/// <summary>
/// When true, emit a bool: whether TAttribute is applied on the enum member.
/// Incompatible with AsArray and Source.
/// </summary>
public bool AsBoolean { get; set; }
}
Example:
[EnumToClass<TestEnum>]
[EnumToClassProperty<Metadata1Attribute>]
[EnumToClassProperty<Metadata2Attribute>(Name = "Meta2")]
[EnumToClassProperty<PermissionAttribute>(AsArray = true, Name = "Permissions", Source = "Name")]
[EnumToClassProperty<AdminOnlyAttribute>(AsBoolean = true, Name = "HasAdminOnly")]
public sealed partial class TestEnumClass { }
Generates properties filled from each enum member’s attributes via object initializers on the static map (constructor stays slim):
| AsBoolean | AsArray | Source | Host type | Value |
|---|---|---|---|---|
| false | false | (null) | TAttribute? |
instance / null |
| false | true | (null) | TAttribute[] |
instances / empty |
| false | false | "Name" |
e.g. string? |
member value / null |
| false | true | "Name" |
e.g. string[] |
values / empty |
| true | false | (null) | bool |
attribute present / absent |
AsBoolean cannot be combined with AsArray or Source (ETC015). Nested Source paths are not supported. Only reconstructible attribute/member values are supported for non-boolean modes.
Equality still compares Value only — projected attribute properties do not participate in Equals / ==.
Diagnostics
| Id | Severity | Meaning |
|---|---|---|
ETC001 |
Error | Host type is not partial |
ETC002 |
Warning | Enum has no named members |
ETC003 |
Error | Host type is nested (not supported; generation skipped) |
ETC010 |
Warning | Attribute type cannot be reconstructed as a property value |
ETC011 |
Error | Duplicate EnumToClassProperty<T> for the same T |
ETC012 |
Error | Invalid or conflicting projected property name |
ETC014 |
Error | Invalid Source member on EnumToClassProperty |
ETC015 |
Error | Conflicting EnumToClassProperty options (AsBoolean vs AsArray/Source) |
Usage
namespace EnumToClass.Tests.Integration;
public enum TestElements
{
None,
Element1,
Element2,
Element3
}
[EnumToClass<TestElements>]
internal sealed partial class TestElementClass
{
}
[EnumToClass<TestElements>(WithDescription = true)]
public sealed partial record TestElementRecord
{
}
Semantics
IsEmpty:truewhenValue == default(TEnum).Empty: shared instance for the default enum value. If a named member equalsdefault(TEnum),Emptyis the same reference as that member’s*Instance(and map entry). Missing names fromGetByNamereturnEmpty.- Flyweight: named members are created once in a static map; conversions and
*Instanceproperties return those instances. GetByName: ordinal, case-sensitive name match; unknown name →Empty.TryGetByName: returnsfalseon miss (and setsvaluetoEmpty).- Classes implement
IEquatable<T>and==/!=byValue. Records use built-in record equality. [Flags]/ combined values: conversion from enum usesToString(); combined flag names are not map keys, so lookup yieldsEmpty. Flags-aware parsing is out of scope.- Nested host types: not supported — generator reports
ETC003and skips code generation (partials would be emitted at namespace scope).
Generated surface (illustrative)
For a partial class host the generator emits (among other members):
ValueByNameMap(private)Empty,Name,Value,IsEmptypublic const string MemberNameandpublic static T MemberNameInstanceper enum memberGetAll(),GetByName,TryGetByName- Implicit conversions:
string,TEnum, underlying integral type ↔ host type - When using
[EnumToClassProperty<T>]: nullable properties for those attribute types
Change Log
Version 1.0.8
- Hardening: Empty flyweight, escaped literals, constant-only enum members, class
IEquatable/==,TryGetByName,ETC001–ETC003,global::BCL types, doc indent, full<summary>forDescription. EnumToClassPropertyAttribute<T>: project selected enum-member attributes as host properties (Name,AsArray,Source,AsBoolean). DiagnosticsETC010–ETC012,ETC014–ETC015.
Version 1.0.7
- Add implicit operator to convert
underlying enum typevalue toClass type.
Version 1.0.6
- Add optional description property generation
Version 1.0.5
- Add documentation comments based on
DescriptionAttributevalue. - Fix full enum type name for external enums.
- Fix documentation comments for external enums.
Version 1.0.4
- Add documentation comments to generated const values based on documentation comments for the enum element
Version 1.0.3
- Fix method names in generator.
- Replace reflection generated to generator generated values dictionary.
- Add GetAll() static function to the class with
EnumToClassAttributeattribute. - Add implicit operator to convert enum type value to underlying enum type.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.