StrongTypeIdGenerator is a C# source generator for strongly typed identifiers.
It helps prevent primitive ID mix-ups by generating domain-specific ID types for string, Guid, and combined (composite) keys.
- Removes boilerplate for strongly typed IDs.
- Prevents accidental mixing of identifiers across boundaries.
- Keeps validation close to the ID type via
CheckValuehooks. - Supports factory-oriented design with optional private constructors.
- Works with
System.ComponentModel.TypeConverterout of the box.
Design decisions:
- Reference types by design. This project prioritizes invariant safety and controlled construction over minimizing allocations, so invalid IDs are harder to create and propagate.
- Built-in precondition hooks. If an ID class defines
CheckValue(...), the method is called from the generated constructor and can validate or normalize input. - Serializer-agnostic core. The main package only relies on
System.ComponentModel.TypeConverterand has no direct dependency onSystem.Text.Json, Newtonsoft.Json, or EF Core converters. - netstandard2.0-friendly usage. IDs can live in
netstandard2.0libraries without extra serialization dependencies. ForSystem.Text.Json, use the optionalStrongTypeIdGenerator.Jsonpackage. For EF Core, use the optionalStrongTypeIdGenerator.EntityFrameworkCorepackage. - First-class composite identifiers.
CombinedIdexists for real-world composite business keys, avoiding ad-hoc wrapper implementations.
StringIdandGuidIdgeneration with value semantics.CombinedIdgeneration for composite identifiers.- Generated equality, comparison, formatting, and operators.
- Optional custom value property name for scalar identifiers.
- Optional constructor privacy (
GenerateConstructorPrivate = true). - Optional
System.Text.Jsonintegration package. - Optional EF Core integration package.
Install package:
dotnet add package StrongTypeIdGeneratorDefine identifiers:
using StrongTypeIdGenerator;
[StringId]
public sealed partial class OrderId
{
}
[GuidId]
public sealed partial class CustomerId
{
}
[CombinedId(typeof(CustomerId), "CustomerId", typeof(OrderId), "OrderId")]
public sealed partial class CustomerOrderId
{
}Generated structure (example for OrderId)
[TypeConverter(typeof(OrderIdConverter))]
public sealed partial class OrderId : ITypedIdentifier<OrderId, string>
{
public OrderId(string value) { ... }
public static OrderId Unspecified { get; } = ...;
public string Value { get; }
public static implicit operator OrderId?(string? value) { ... }
public static implicit operator string?(OrderId? value) { ... }
public bool Equals(OrderId? other) { ... }
public int CompareTo(OrderId? other) { ... }
public override bool Equals(object? obj) { ... }
public override int GetHashCode() { ... }
public override string ToString() { ... }
public string ToString(string? format, IFormatProvider? provider) { ... }
public static bool operator ==(OrderId left, OrderId right) { ... }
public static bool operator !=(OrderId left, OrderId right) { ... }
public static bool operator <(OrderId left, OrderId right) { ... }
public static bool operator <=(OrderId left, OrderId right) { ... }
public static bool operator >(OrderId left, OrderId right) { ... }
public static bool operator >=(OrderId left, OrderId right) { ... }
private sealed partial class OrderIdConverter : TypeToStringConverter<OrderId>
{
protected override string? InternalConvertToString(OrderId value) { ... }
protected override OrderId? InternalConvertFromString(string value) { ... }
}
}The generator creates immutable reference-type identifiers with:
- constructor (public or private based on attribute options)
- typed value/component properties
UnspecifiedEquals,GetHashCode, comparison operatorsToStringand format overloads- implicit conversion operators
- nested
TypeConverter
For System.Text.Json, install:
dotnet add package StrongTypeIdGenerator.JsonConfigure serializer:
using StrongTypeIdGenerator.Json;
var options = new JsonSerializerOptions();
options.Converters.Add(new TypeConverterJsonConverterFactory());For EF Core integration, install StrongTypeIdGenerator.EntityFrameworkCore and see the EF Core Integration guide.
Detailed docs are in the docs folder:
- Docs Index
- Getting Started
- String IDs
- Guid IDs
- Combined IDs
- Custom Validation (CheckValue)
- Custom Value Property Name
- Private Constructors and Factories
- TypeConverter and System.Text.Json
- EF Core Integration
- Design Decisions
- FAQ
Inspired by StronglyTypedId.