Generated Code¶
Every [TypedId] struct receives a complete value-type implementation via source generation. The generated code is visible in your IDE under the Analyzers → Deepstaging.Generators node.
Generated Members¶
| Member | Description |
|---|---|
Value property |
The underlying backing value |
| Constructor | new UserId(Guid value) |
IEquatable<T> |
Value-based Equals, GetHashCode, ==, != |
IComparable<T> |
Value-based CompareTo, >, <, >=, <= |
IFormattable |
Format-string overload of ToString |
ISpanFormattable |
Span-based formatting (.NET 6+) |
IParsable<T> |
Parse(string) and TryParse (.NET 7+) |
ISpanParsable<T> |
Span-based parsing (.NET 7+) |
IUtf8SpanFormattable |
UTF-8 span formatting (.NET 8+) |
IUtf8SpanParsable<T> |
UTF-8 span parsing (.NET 8+, numeric types) |
ToString() |
Returns the backing value as a string |
Empty |
Static readonly field with the default/empty value |
New() |
Factory method (Guid only — creates a v7 UUID) |
Parse(string) |
Static parse method for all backing types |
| Implicit conversion | From backing type → typed ID |
| Explicit conversion | From typed ID → backing type |
TypeConverter |
Always generated — enables ASP.NET model binding |
var id = UserId.New(); // v7 UUID
var parsed = UserId.Parse("..."); // from string
var empty = UserId.Empty; // Guid.Empty
Guid raw = (Guid)id; // explicit cast
UserId fromGuid = Guid.NewGuid(); // implicit conversion
bool eq = id == parsed; // value equality
String Validation¶
String-backed IDs validate against null and empty strings in the constructor:
- On .NET 7+ — uses
ArgumentException.ThrowIfNullOrEmpty - On older targets — throws
ArgumentNullException
This ensures that a string-backed typed ID always holds a meaningful value.
[TypedId(BackingType = BackingType.String)]
public readonly partial struct ExternalId;
var id = new ExternalId("ext-123"); // ✅ OK
var bad = new ExternalId(""); // ❌ throws ArgumentException
Usage Patterns¶
In Records and DTOs¶
As Dictionary Keys¶
With JsonConverter enabled, typed IDs work as JSON dictionary keys via generated ReadAsPropertyName / WriteAsPropertyName:
var lookup = new Dictionary<UserId, string>
{
[UserId.New()] = "Alice"
};
var json = JsonSerializer.Serialize(lookup); // keys serialize as strings
In EF Core Models¶
With EfCoreValueConverter enabled:
[TypedId(Converters = IdConverters.EfCoreValueConverter)]
public readonly partial struct OrderId;
public class Order
{
public OrderId Id { get; set; }
public string Name { get; set; } = "";
}
// In DbContext.OnModelCreating:
modelBuilder.Entity<Order>()
.Property(e => e.Id)
.HasConversion<OrderId.EfCoreValueConverter>();