EnumRecords 0.3.0
See the version list below for details.
dotnet add package EnumRecords --version 0.3.0
NuGet\Install-Package EnumRecords -Version 0.3.0
<PackageReference Include="EnumRecords" Version="0.3.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="EnumRecords" Version="0.3.0" />
<PackageReference Include="EnumRecords"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add EnumRecords --version 0.3.0
#r "nuget: EnumRecords, 0.3.0"
#:package EnumRecords@0.3.0
#addin nuget:?package=EnumRecords&version=0.3.0
#tool nuget:?package=EnumRecords&version=0.3.0
EnumRecords
A C# source generator that associates compile-time constant data properties with enum values, enabling property-like access via generated extension methods.
Features
- 🚀 Zero runtime overhead — All code is generated at compile time
- 📦 No runtime dependencies — Attributes are source-generated into your project
- 🔍 IntelliSense support — Full IDE autocomplete for generated extension methods
- ✅ Type-safe — Compile-time validation of property types and values
- 🎯 Simple API — Just two attributes to learn
- 🔄 Reverse lookup — Find enum values by property values with
[ReverseLookup] - 📋 Collection access — Get all property values via
Get{PropertyName}s()methods
Installation
NuGet Package
dotnet add package EnumRecords
Note: EnumRecords is a development-only dependency. NuGet automatically configures it with
PrivateAssets="all"so it won't become a transitive dependency of your consumers.
Project Reference
For local development, add a reference to the generator project:
<ItemGroup>
<ProjectReference Include="path/to/EnumRecords.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
Quick Start
1. Define a Properties Record Struct
Create a readonly record struct that defines the schema for your enum's associated data:
public readonly record struct ColorEnumProperties(
string Name,
int Value,
string HexCode
);
2. Decorate Your Enum
Apply [EnumRecord<T>] to your enum and [EnumRecordProperties(...)] to each member:
using EnumRecords;
[EnumRecord<ColorEnumProperties>]
public enum EColors : int
{
[EnumRecordProperties("Red", 1, "#FF0000")]
Red = 1,
[EnumRecordProperties("Green", 2, "#00FF00")]
Green = 2,
[EnumRecordProperties("Blue", 3, "#0000FF")]
Blue = 3,
}
3. Access Properties via Extension Methods
The generator creates extension methods for each property in your record struct:
// Access properties like methods on enum values
string hex = EColors.Red.HexCode(); // "#FF0000"
string name = EColors.Green.Name(); // "Green"
int value = EColors.Blue.Value(); // 3
// Works with variables too
EColors color = EColors.Red;
Console.WriteLine(color.HexCode()); // "#FF0000"
// Iterate over all values
foreach (EColors c in Enum.GetValues<EColors>())
{
Console.WriteLine($"{c}: {c.Name()} - {c.HexCode()}");
}
Supported Property Types
The [EnumRecordProperties] attribute accepts any compile-time constant values:
| Type | Example |
|---|---|
string |
"Hello" |
int, long, short, byte |
42, 100L |
uint, ulong, ushort, sbyte |
42U, 100UL |
float, double, decimal |
3.14f, 3.14d, 3.14m |
bool |
true, false |
char |
'A' |
Reverse Lookup
You can mark properties with [ReverseLookup] to generate methods that find an enum value by its property value:
Setup
Add [ReverseLookup] to the constructor parameter in your properties record struct:
public readonly record struct ColorEnumProperties(
string Name,
int Value,
[ReverseLookup] string HexCode // Enable reverse lookup for HexCode
);
Generated Methods
For each property marked with [ReverseLookup], two static methods are generated:
// Non-throwing variant - returns false if not found
public static bool TryFromHexCode(string value, out EColors result);
// Throwing variant - throws ArgumentException if not found
public static EColors FromHexCode(string value);
Usage
// Find enum by property value (throwing)
EColors red = EColorsExtensions.FromHexCode("#FF0000"); // Returns EColors.Red
// Find enum by property value (non-throwing)
if (EColorsExtensions.TryFromHexCode("#00FF00", out var color))
{
Console.WriteLine(color); // Green
}
// Handle not found
if (!EColorsExtensions.TryFromHexCode("#FFFFFF", out _))
{
Console.WriteLine("Color not found");
}
// Throwing variant for unknown values
try
{
var unknown = EColorsExtensions.FromHexCode("#FFFFFF");
}
catch (ArgumentException ex)
{
// "No EColors found with HexCode '#FFFFFF'"
}
Uniqueness Requirement
Properties marked with [ReverseLookup] must have unique values across all enum members. The generator emits a compile-time error (ENUMREC001) if duplicate values are detected:
// ❌ This will cause compile error ENUMREC001
public readonly record struct BadProps([ReverseLookup] string Code);
[EnumRecord<BadProps>]
public enum BadEnum
{
[EnumRecordProperties("A")]
First,
[EnumRecordProperties("A")] // Error: Duplicate value '"A"' for reverse-lookup property 'Code'
Second,
}
Case-Insensitive String Lookup
For string properties, you can enable case-insensitive lookups with IgnoreCase = true:
public readonly record struct FileTypeProperties(
string Extension,
[ReverseLookup(IgnoreCase = true)] string MimeType
);
[EnumRecord<FileTypeProperties>]
public enum FileType
{
[EnumRecordProperties(".json", "application/json")]
Json,
[EnumRecordProperties(".xml", "application/xml")]
Xml,
}
// Usage - all these will match FileType.Json
FileTypeExtensions.FromMimeType("application/json"); // exact match
FileTypeExtensions.FromMimeType("APPLICATION/JSON"); // uppercase
FileTypeExtensions.FromMimeType("Application/Json"); // mixed case
Note: When using
IgnoreCase = true, the uniqueness check also uses case-insensitive comparison. For example,"ABC"and"abc"would be considered duplicates.
Get All Property Values
For each property in your record struct, the generator creates a Get{PropertyName}s() method that returns all defined values as a read-only list:
Generated Methods
// For ColorEnumProperties with Name, Value, and HexCode properties:
public static IReadOnlyList<string> GetNames();
public static IReadOnlyList<int> GetValues();
public static IReadOnlyList<string> GetHexCodes();
Usage
// Get all property values as collections
var names = EColorsExtensions.GetNames(); // ["Red", "Green", "Blue"]
var values = EColorsExtensions.GetValues(); // [1, 2, 3]
var hexCodes = EColorsExtensions.GetHexCodes(); // ["#FF0000", "#00FF00", "#0000FF"]
// Useful for validation, dropdowns, etc.
if (EColorsExtensions.GetHexCodes().Contains(userInput))
{
// Valid hex code
}
// Or with FileType enum
var extensions = FileTypeExtensions.GetExtensions(); // [".json", ".xml", ".csv"]
var mimeTypes = FileTypeExtensions.GetMimeTypes(); // ["application/json", "application/xml", "text/csv"]
Advanced Examples
HTTP Status Codes
public readonly record struct HttpStatusProperties(
int Code,
string Phrase,
bool IsSuccess
);
[EnumRecord<HttpStatusProperties>]
public enum HttpStatus
{
[EnumRecordProperties(200, "OK", true)]
Ok = 200,
[EnumRecordProperties(201, "Created", true)]
Created = 201,
[EnumRecordProperties(400, "Bad Request", false)]
BadRequest = 400,
[EnumRecordProperties(404, "Not Found", false)]
NotFound = 404,
[EnumRecordProperties(500, "Internal Server Error", false)]
InternalServerError = 500,
}
// Usage
if (HttpStatus.Ok.IsSuccess())
{
Console.WriteLine(HttpStatus.Ok.Phrase()); // "OK"
}
File Types
public readonly record struct FileTypeProperties(
string Extension,
string MimeType,
string Description
);
[EnumRecord<FileTypeProperties>]
public enum FileType
{
[EnumRecordProperties(".json", "application/json", "JSON Document")]
Json,
[EnumRecordProperties(".xml", "application/xml", "XML Document")]
Xml,
[EnumRecordProperties(".csv", "text/csv", "Comma-Separated Values")]
Csv,
}
// Usage
string mime = FileType.Json.MimeType(); // "application/json"
API Reference
EnumRecordAttribute<TProperties>
Marks an enum as having associated record properties.
[EnumRecord<TProperties>]
public enum MyEnum { ... }
TPropertiesmust be astruct(typically areadonly record struct)- Applied to the enum declaration
EnumRecordPropertiesAttribute
Specifies the property values for an enum member.
[EnumRecordProperties(arg1, arg2, ...)]
EnumMember = value,
- Arguments are positional and must match the order of the properties record struct's constructor parameters
- All arguments must be compile-time constants
ReverseLookupAttribute
Marks a property for reverse lookup, enabling lookup of enum values by property value.
public readonly record struct MyProperties([ReverseLookup] string UniqueId);
- Applied to constructor parameters of the properties record struct
- Property values must be unique across all enum members (enforced at compile time)
- Generates
TryFrom{PropertyName}andFrom{PropertyName}static methods
Properties:
| Property | Type | Default | Description |
|---|---|---|---|
IgnoreCase |
bool |
false |
Enable case-insensitive matching for string lookups |
Requirements
- .NET 6.0+ or .NET Standard 2.0+ consuming project
- C# 9.0+ (for record struct support in consuming code)
Building from Source
# Clone the repository
git clone https://github.com/dsisco11/EnumRecords.git
cd EnumRecords
# Build the generator
dotnet build EnumRecords.csproj
# Build and run tests
dotnet run --project EnumRecords.Tests/EnumRecords.Tests.csproj
How It Works
- Post-Initialization: The generator emits the
EnumRecordAttribute<T>andEnumRecordPropertiesAttributetypes as source code into your compilation - Syntax Analysis: Finds all enums decorated with
[EnumRecord<T>] - Semantic Analysis: Extracts the properties type
Tand reads constructor parameters to determine property names and types - Code Generation: For each decorated enum, generates a static extension class with one method per property using switch expressions
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
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.