FractalDataWorks.EnhancedEnums 0.1.28-alpha-g0f79040e54

This is a prerelease version of FractalDataWorks.EnhancedEnums.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package FractalDataWorks.EnhancedEnums --version 0.1.28-alpha-g0f79040e54
                    
NuGet\Install-Package FractalDataWorks.EnhancedEnums -Version 0.1.28-alpha-g0f79040e54
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FractalDataWorks.EnhancedEnums" Version="0.1.28-alpha-g0f79040e54">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FractalDataWorks.EnhancedEnums" Version="0.1.28-alpha-g0f79040e54" />
                    
Directory.Packages.props
<PackageReference Include="FractalDataWorks.EnhancedEnums">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FractalDataWorks.EnhancedEnums --version 0.1.28-alpha-g0f79040e54
                    
#r "nuget: FractalDataWorks.EnhancedEnums, 0.1.28-alpha-g0f79040e54"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FractalDataWorks.EnhancedEnums@0.1.28-alpha-g0f79040e54
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FractalDataWorks.EnhancedEnums&version=0.1.28-alpha-g0f79040e54&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=FractalDataWorks.EnhancedEnums&version=0.1.28-alpha-g0f79040e54&prerelease
                    
Install as a Cake Tool

FractalDataWorks Enhanced Enums

NuGet License

Advanced enumeration patterns with source generation for .NET applications.

Table of Contents

Overview

FractalDataWorks Enhanced Enums provides a powerful alternative to standard C# enums with:

  • Type-safe enumeration patterns with compile-time validation
  • Source generation for zero boilerplate
  • High-performance lookups with O(1) dictionary access
  • Rich metadata support through properties and attributes
  • Cross-assembly support for shared enum definitions
  • Empty value pattern for "no selection" scenarios
  • Static property accessors for direct enum value access

Installation

NuGet Package

dotnet add package FractalDataWorks.EnhancedEnums

Package Reference

<PackageReference Include="FractalDataWorks.EnhancedEnums" Version="*" />

Quick Start

1. Define Your Enhanced Enum

using FractalDataWorks.EnhancedEnums.Attributes;

[EnhancedEnumBase]
public abstract class OrderStatus
{
    protected OrderStatus(string name, string description)
    {
        Name = name;
        Description = description;
    }
    
    public string Name { get; }
    public string Description { get; }
    
    [EnumLookup]
    public abstract string Code { get; }
}

[EnumOption]
public class Pending : OrderStatus
{
    public Pending() : base("Pending", "Order is pending") { }
    public override string Code => "PEND";
}

[EnumOption]
public class Shipped : OrderStatus
{
    public Shipped() : base("Shipped", "Order has shipped") { }
    public override string Code => "SHIP";
}

2. Use the Generated Collection

// Get all values
foreach (var status in OrderStatuses.All)
{
    Console.WriteLine($"{status.Name}: {status.Description}");
}

// Lookup by name
var pending = OrderStatuses.GetByName("Pending");

// Lookup by custom property
var shipped = OrderStatuses.GetByCode("SHIP");

// Direct static access
var status = OrderStatuses.Pending;

// Empty value
var none = OrderStatuses.Empty;

Features

Lookup Properties

Mark properties with [EnumLookup] to generate efficient lookup methods:

[EnhancedEnumBase]
public abstract class Country
{
    public abstract string Name { get; }
    
    [EnumLookup]
    public abstract string IsoCode { get; }
    
    [EnumLookup(MethodName = "FindByCurrency")]
    public abstract string Currency { get; }
}

// Usage
var us = Countries.GetByIsoCode("US");
var euroCountries = Countries.FindByCurrency("EUR");

Multiple Collections

Support multiple categorizations of the same base type:

[EnhancedEnumBase("ActiveStatuses")]
[EnhancedEnumBase("ErrorStatuses")]
public abstract class Status
{
    public abstract string Name { get; }
}

[EnumOption(CollectionName = "ActiveStatuses")]
public class Running : Status { }

[EnumOption(CollectionName = "ErrorStatuses")]
public class Failed : Status { }

Interface-Based Return Types

Control return types for flexible hierarchies:

public interface IOrderStatus : IEnhancedEnumOption
{
    string Description { get; }
}

[EnhancedEnumBase(ReturnType = "IOrderStatus")]
public abstract class OrderStatus : IOrderStatus
{
    public abstract int Id { get; }
    public abstract string Name { get; }
    public abstract string Description { get; }
}

Cross-Assembly Support (Service Type Pattern)

Enhanced Enums fully supports the Service Type Pattern, allowing enum options to be discovered from multiple assemblies at compile time. This enables plugin architectures where new options can be added without modifying the base assembly.

How it works:

  1. Define your base enum type in a shared assembly with [EnhancedEnumBase]
  2. Create option types in plugin assemblies with [EnumOption]
  3. Plugin assemblies declare which assemblies can discover them using MSBuild properties
  4. The generator discovers ALL options at compile time and includes them in the generated collection

Configuration:

Plugin assemblies opt-in to discovery by declaring which assemblies can discover them in their .csproj:


<PropertyGroup>
  
  <IncludeInEnhancedEnumAssemblies>Main;FractalDataWorks.Services</IncludeInEnhancedEnumAssemblies>
</PropertyGroup>


<PropertyGroup>
  
  <IncludeInEnhancedEnumAssemblies>MyApp.Core;MyApp.Services;MyApp.Web</IncludeInEnhancedEnumAssemblies>
</PropertyGroup>

Example - Plugin Architecture:

// Shared.dll - Base definition
[EnhancedEnumBase(IncludeReferencedAssemblies = true)]
public abstract class ServiceType
{
    public abstract string Name { get; }
    public abstract Type ImplementationType { get; }
}

// PluginA.dll - Plugin assembly (with IncludeInEnhancedEnumAssemblies=Main)
[EnumOption]
public class EmailService : ServiceType
{
    public override string Name => "Email";
    public override Type ImplementationType => typeof(SmtpEmailProvider);
}

// PluginB.dll - Another plugin (with IncludeInEnhancedEnumAssemblies=Main)
[EnumOption]
public class SmsService : ServiceType
{
    public override string Name => "SMS";
    public override Type ImplementationType => typeof(TwilioSmsProvider);
}

// Main.dll - Application using the services
// The generated ServiceTypes collection includes BOTH EmailService and SmsService!
var allServices = ServiceTypes.All; // Contains instances from both plugins
var emailService = ServiceTypes.GetByName("Email"); // Works!

Important:

  • Plugin assemblies must explicitly opt-in to discovery via <IncludeInEnhancedEnumAssemblies>
  • The generator reads compiled assembly metadata at compile time (not runtime)
  • Only assemblies that opt-in will have their enum options discovered
  • This provides security by preventing unwanted assemblies from injecting options

Generic Enhanced Enums

Enhanced Enums now supports generic base types. Use the standard [EnhancedEnumBase] attribute:

[EnhancedEnumBase]
public abstract class Container<T> where T : IDisposable
{
    public abstract string Name { get; }
    public abstract T Value { get; }
}

[EnumOption]
public class StringContainer : Container<string>
{
    public override string Name => "String";
    public override string Value => "Default";
}

[EnumOption]
public class StreamContainer : Container<FileStream>
{
    public override string Name => "Stream";
    public override FileStream Value => new FileStream(...);
}

The generator will:

  • Extract type parameters and constraints
  • Add required using statements from constraint types
  • Generate type-safe collections

For generic types with complex constraints, you can specify a default return type:

[EnhancedEnumBase(
    DefaultGenericReturnType = "IService",
    DefaultGenericReturnTypeNamespace = "MyApp.Services")]
public abstract class ServiceType<T> where T : IService
{
    public abstract string Name { get; }
}

Performance

Enhanced Enums are optimized for high-performance scenarios:

graph LR
    A[Lookup Request] --> B{Lookup Type}
    B -->|By Name| C[O(1) Dictionary]
    B -->|By Property| D[O(1) Dictionary]
    B -->|All Values| E[Cached Array]
    C --> F[Zero Allocations]
    D --> F
    E --> F

Benchmark results show:

  • 9x faster lookups compared to LINQ searches
  • Zero allocations for all operations
  • 35% additional improvement with .NET 8+ FrozenDictionary

Architecture

Source Generation Flow

sequenceDiagram
    participant Code as Your Code
    participant Attr as Attributes
    participant Gen as Source Generator
    participant Comp as Compiler
    participant Out as Generated Code
    
    Code->>Attr: Apply [EnhancedEnumBase]
    Code->>Attr: Apply [EnumOption]
    Attr->>Gen: Trigger generation
    Gen->>Gen: Scan types
    Gen->>Gen: Build collection
    Gen->>Out: Generate static class
    Out->>Comp: Compile together
    Comp->>Code: Available at compile time

Generated Code Structure

classDiagram
    class OrderStatus {
        <<abstract>>
        +string Name
        +string Description
        +string Code
    }
    
    class Pending {
        +Pending()
        +string Code = "PEND"
    }
    
    class Shipped {
        +Shipped()
        +string Code = "SHIP"
    }
    
    class OrderStatuses {
        <<static>>
        +ImmutableArray~OrderStatus~ All
        +OrderStatus Empty
        +OrderStatus Pending
        +OrderStatus Shipped
        +GetByName(string) OrderStatus?
        +GetByCode(string) OrderStatus?
    }
    
    OrderStatus <|-- Pending
    OrderStatus <|-- Shipped
    OrderStatuses ..> OrderStatus : manages

API Reference

Attributes

[EnhancedEnumBase]

Marks a class as an enhanced enum base type.

[EnhancedEnumBase(
    CollectionName = "MyStatuses",              // Custom collection name
    UseFactory = false,                         // Use factory pattern
    NameComparison = StringComparison.OrdinalIgnoreCase,  // Name comparison
    IncludeReferencedAssemblies = false,        // Cross-assembly scanning
    ReturnType = "IMyStatus"                    // Custom return type
)]
[EnumOption]

Marks a class as an enum option.

[EnumOption(
    Name = "CustomName",           // Override display name
    Order = 1,                     // Sort order
    CollectionName = "MyCollection" // Target collection
)]
[EnumLookup]

Marks a property for lookup generation.

[EnumLookup(
    MethodName = "FindByCode",     // Custom method name
    AllowMultiple = false,         // Allow multiple matches
    ReturnType = "IMyStatus"       // Custom return type
)]

Generated Methods

Every generated collection includes:

  • ImmutableArray<T> All - All enum values
  • T Empty - Empty/none value
  • T? GetByName(string name) - Lookup by name
  • T? GetByXxx(...) - Custom lookups for [EnumLookup] properties
  • Static properties for each enum value

Developer Guide

Project Structure

FractalDataWorks.EnhancedEnums/
├── src/
│   ├── Attributes/           # Attribute definitions
│   ├── Analyzers/           # Roslyn analyzers
│   ├── Generators/          # Source generators
│   └── Models/              # Data models
├── tests/                   # Unit tests
├── benchmarks/             # Performance benchmarks
└── samples/                # Example projects

Building from Source

# Clone repository
git clone https://github.com/FractalDataWorks/enhanced-enums.git

# Build
dotnet build

# Run tests
dotnet test

# Run benchmarks
dotnet run -c Release --project benchmarks/FractalDataWorks.EnhancedEnums.Benchmarks

Adding New Features

  1. Attributes: Define in Attributes/ folder
  2. Generation Logic: Modify EnhancedEnumGenerator.cs
  3. Tests: Add to appropriate test project
  4. Documentation: Update this README

Testing Source Generators

[Fact]
public void GeneratesCollectionClass()
{
    var source = @"
        [EnhancedEnumBase]
        public abstract class Status { }
        
        [EnumOption]
        public class Active : Status { }
    ";
    
    var result = TestHelper.GenerateSource(source);
    
    result.ShouldContain("public static class Statuses");
    result.ShouldContain("public static Status Active");
}

Debugging Tips

  1. Enable generator logging:

    <PropertyGroup>
      <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    </PropertyGroup>
    
  2. Check generated files: Look in obj/Generated/

  3. Use diagnostics: The generator reports informational diagnostics

Performance Considerations

  1. Use constructor patterns for better performance
  2. Avoid complex logic in enum constructors
  3. Consider .NET 8+ for FrozenDictionary benefits
  4. Cache enum instances - they're singletons

Troubleshooting

Source Generator Not Running

  1. Ensure proper package/project reference configuration
  2. Check for build errors preventing generation
  3. Clean and rebuild the solution

Missing Generated Code

  1. Verify attributes are applied correctly
  2. Check that base class is abstract
  3. Ensure enum options are public and non-abstract

Performance Issues

  1. Review constructor complexity
  2. Check for excessive cross-assembly scanning
  3. Profile with included benchmarks

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

Code Style

  • Follow existing patterns
  • Add XML documentation
  • Include unit tests
  • Update benchmarks if needed

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (8)

Showing the top 5 NuGet packages that depend on FractalDataWorks.EnhancedEnums:

Package Downloads
FractalDataWorks.Connections

Package Description

FractalDataWorks.Services

Package Description

FractalDataWorks.Tools

Package Description

FractalDataWorks.Services.ExternalConnections.Abstractions

Package Description

FractalDataWorks.Services.SecretManagement.Abstractions

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.