Skip to content

Attribute Reference

This page documents the attributes used to define and configure typed IDs.

[TypedId]

Marks a partial struct as a strongly-typed ID. The source generator produces a full value-type implementation including equality, comparison, parsing, formatting, and a TypeConverter.

using Deepstaging.Ids;

[TypedId]
public readonly partial struct UserId;

Properties

Property Type Default Description
BackingType BackingType Guid The underlying primitive type
Converters IdConverters None Which serialization converters to generate
Profile string? null Name of the [TypedIdProfile] to apply
[TypedId(BackingType = BackingType.Int)]
public readonly partial struct OrderId;

[TypedId(Converters = IdConverters.JsonConverter | IdConverters.EfCoreValueConverter)]
public readonly partial struct CustomerId;

Backing Types

Value CLR Type Empty Value Factory
Guid System.Guid Guid.Empty New() generates a v7 UUID
Int int 0 No parameterless New()
Long long 0 No parameterless New()
String string string.Empty No parameterless New()

String null-checking

String-backed IDs validate against null and empty strings in the constructor. On .NET 7+ this uses ArgumentException.ThrowIfNullOrEmpty; on older targets it throws ArgumentNullException.

Converters

IdConverters is a flags enum — combine with |:

Flag What it generates
JsonConverter System.Text.Json JsonConverter<T> nested class
EfCoreValueConverter EF Core ValueConverter<T, TBacking> nested class

A System.ComponentModel.TypeConverter is always generated regardless of flags. See the Converters page for details.

[TypedId(Converters = IdConverters.JsonConverter | IdConverters.EfCoreValueConverter)]
public readonly partial struct ProductId;

[TypedIdProfile]

Assembly-level attribute that defines a named or default configuration profile for [TypedId] structs. Multiple profiles can coexist in a single assembly. Use [TypedId(Profile = "name")] to select a profile.

An unnamed (default) profile applies to every [TypedId] that does not specify a Profile. Only one unnamed profile is allowed per assembly.

// Default profile — applies to [TypedId] without a Profile
[assembly: TypedIdProfile(Converters = IdConverters.JsonConverter)]

// Named profile for full-stack persistence
[assembly: TypedIdProfile("persistence",
    Converters = IdConverters.EfCoreValueConverter | IdConverters.JsonConverter)]
[TypedId]
public readonly partial struct UserId;              // gets JsonConverter from default profile

[TypedId(Profile = "persistence")]
public readonly partial struct OrderId;             // gets EfCore + Json from named profile

[TypedId(BackingType = BackingType.String, Profile = "persistence")]
public readonly partial struct ExternalId;          // String overrides profile's Guid default
Property Type Default Description
Name string "" Profile name (unnamed = default profile)
BackingType BackingType Guid Default backing type for matching IDs
Converters IdConverters None Default converters for matching IDs

[StreamId]

Companion attribute for [TypedId] that layers event stream identity members onto a typed ID struct. Generates a StreamName property and FromStreamName static parser for use with event-sourced aggregates.

Requirements

  • The struct must also have [TypedId] (diagnostic DSID03).
  • Only Guid and String backing types are supported (diagnostic DSID04).

Properties

Property Type Default Description
Prefix string? Type name without Id suffix, lowercased Stream name prefix (e.g., OrderId"order")
Separator string "-" Separator between prefix and value

Generated Members

Member Description
StreamName Property formatted as {Prefix}{Separator}{Value}
FromStreamName(string) Static method that parses a stream name back to the typed ID

Examples

Default prefix (derived from type name):

[TypedId]
[StreamId]
public readonly partial struct OrderId;

var id = OrderId.New();
id.StreamName;                              // "order-550e8400-e29b-41d4-a716-446655440000"
OrderId.FromStreamName("order-550e8400-…"); // parses back to OrderId

Custom prefix and separator:

[TypedId]
[StreamId(Prefix = "ord", Separator = ":")]
public readonly partial struct OrderId;

var id = OrderId.New();
id.StreamName; // "ord:550e8400-e29b-41d4-a716-446655440000"

Diagnostics

ID Severity Description Code Fix
DSID01 Error TypedId struct must be partial Add partial modifier
DSID02 Warning TypedId struct should be readonly
DSID03 Error StreamId requires TypedId
DSID04 Warning StreamId requires Guid or String backing type
DSID05 Error TypedId references unknown profile
DSID06 Error Duplicate default TypedId profile