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)
{
}
}
| Parameter | Purpose |
|---|
name | Human-readable string name, used for serialisation and display. Accessible via the inherited Name property. |
value | Integer 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.