Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jordiaragonzaragoza/JordiAragonZaragoza.SharedKernel/llms.txt

Use this file to discover all available pages before exploring further.

Standard C# enum types are little more than named integers. They can be cast from any int, they carry no behaviour, and they are trivially misused — nothing stops a developer from writing (OrderStatus)42 and producing a value your domain never intended to allow. In a rich domain model, status and type fields deserve the same care as any other concept. SharedKernel’s SmartEnum<TEnum> wraps Ardalis.SmartEnum to give you a class-based enumeration that is type-safe, extensible with behaviour, and maps cleanly to EF Core.

SmartEnum<TEnum>

SmartEnum<TEnum> is an abstract base class that wraps Ardalis.SmartEnum.SmartEnum<TEnum, int>, fixing the value type to int so every SharedKernel enum is backed by an integer — consistent with standard C# enum conventions and efficient for database storage.
public abstract class SmartEnum<TEnum> : Ardalis.SmartEnum.SmartEnum<TEnum>
    where TEnum : Ardalis.SmartEnum.SmartEnum<TEnum, int>
{
    protected SmartEnum(string name, int value)
        : base(name, value)
    {
    }
}
ParameterPurpose
nameHuman-readable string name, used for serialisation and display. Accessible via the inherited Name property.
valueInteger value stored in the database. Accessible via the inherited Value property.
The base class from Ardalis.SmartEnum additionally provides:
  • SmartEnum<TEnum>.List — a static list of all defined members.
  • SmartEnum<TEnum>.FromName(string name) — look up a member by its name.
  • SmartEnum<TEnum>.FromValue(int value) — look up a member by its integer value.
  • Equality operators comparing by value.

Defining a SmartEnum

Declare your enumeration as a sealed class with static readonly members, one per permitted value:
public sealed class OrderStatus : SmartEnum<OrderStatus>
{
    public static readonly OrderStatus Pending   = new(nameof(Pending),   1);
    public static readonly OrderStatus Confirmed = new(nameof(Confirmed), 2);
    public static readonly OrderStatus Shipped   = new(nameof(Shipped),   3);
    public static readonly OrderStatus Cancelled = new(nameof(Cancelled), 4);

    private OrderStatus(string name, int value)
        : base(name, value)
    {
    }
}
Usage in the domain:
// Access a specific member
OrderStatus status = OrderStatus.Pending;

// Compare by value
if (status == OrderStatus.Shipped) { /* ... */ }

// Enumerate all valid values — impossible with a plain C# enum without reflection
foreach (var s in OrderStatus.List)
{
    Console.WriteLine($"{s.Name} ({s.Value})");
}

// Parse from a stored integer (e.g. from an external message)
OrderStatus fromDb = OrderStatus.FromValue(2);   // OrderStatus.Confirmed

// Parse from a name string
OrderStatus fromName = OrderStatus.FromName("Shipped");  // OrderStatus.Shipped

Adding behaviour

Because OrderStatus is a class, you can add methods and properties directly:
public sealed class OrderStatus : SmartEnum<OrderStatus>
{
    public static readonly OrderStatus Pending   = new(nameof(Pending),   1, canBeShipped: false);
    public static readonly OrderStatus Confirmed = new(nameof(Confirmed), 2, canBeShipped: true);
    public static readonly OrderStatus Shipped   = new(nameof(Shipped),   3, canBeShipped: false);
    public static readonly OrderStatus Cancelled = new(nameof(Cancelled), 4, canBeShipped: false);

    private OrderStatus(string name, int value, bool canBeShipped)
        : base(name, value)
    {
        this.CanBeShipped = canBeShipped;
    }

    public bool CanBeShipped { get; }
}
In the aggregate:
public void Ship()
{
    CheckRule(new OrderMustBeEligibleForShippingRule(this.Status.CanBeShipped));
    this.Apply(new OrderShippedEvent(this.Id.Value, DateTimeOffset.UtcNow));
}

EF Core mapping with Ardalis.SmartEnum.EFCore

SharedKernel’s BaseContext calls configurationBuilder.ConfigureSmartEnum() inside ConfigureConventions, which registers a global EF Core value converter for every SmartEnum property. No per-property configuration is required.
// Infrastructure — BaseContext.cs
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.ConfigureSmartEnum();   // global SmartEnum convention

    base.ConfigureConventions(configurationBuilder);
}
Your derived DbContext only needs to inherit from BaseContext:
public sealed class OrderingDbContext : BaseContext
{
    public OrderingDbContext(
        DbContextOptions<OrderingDbContext> options,
        ILoggerFactory loggerFactory,
        IHostEnvironment hostEnvironment)
        : base(options, loggerFactory, hostEnvironment)
    {
    }

    public DbSet<Order> Orders => this.Set<Order>();
}
EF Core will then store OrderStatus.Value (an int) in the database column and transparently convert it back to OrderStatus when reading — no manual converter configuration needed per entity.
Use SmartEnum for every domain status and type field, especially when:
  • The enumeration is used in domain logic or business rules (e.g. status.CanBeShipped).
  • You need to add new members without modifying switch statements everywhere.
  • You want to prevent invalid integer values from being cast into a valid-looking status.
Plain C# enum is still fine for non-domain concerns such as configuration options or framework flags where behaviour is not needed.

Build docs developers (and LLMs) love