State Machine
Entities with a status enum can enforce valid state transitions at compile time with
[StateMachine<TEnum>]. The source generator turns the enum’s [TransitionFrom] declarations into
guarded transition methods, so an invalid transition is a typed error — never an unchecked status
assignment. The attribute itself is listed in Attributes; this page is the full
guide. For how transitions fit a mutation, see the Mutation Pipeline.
Declaration
Section titled “Declaration”Annotate the enum members with the states they may be reached from, mark the initial state, and put
[StateMachine<TEnum>] on the entity:
public enum ReservationStatus{ [InitialState] Pending,
[TransitionFrom(ReservationStatus.Pending)] Confirmed,
[TransitionFrom(ReservationStatus.Confirmed)] PaymentReceived,
[TransitionFrom(ReservationStatus.Confirmed)] [TransitionFrom(ReservationStatus.PaymentReceived)] CheckedIn,
[TransitionFrom(ReservationStatus.CheckedIn)] CheckedOut,
[TransitionFrom(ReservationStatus.Pending)] [TransitionFrom(ReservationStatus.Confirmed)] [TransitionFrom(ReservationStatus.PaymentReceived)] Cancelled,
[TransitionFrom(ReservationStatus.Pending)] [TransitionFrom(ReservationStatus.Confirmed)] NoShow}
[Entity<Guid>][StateMachine<ReservationStatus>]public partial class Reservation : IEntity<Guid>{ public ReservationStatus Status { get; private set; } = ReservationStatus.Pending;}Generated members
Section titled “Generated members”The source generator produces, on the entity:
TransitionTo(newState)— returnsVoidResult<IError>(success, or a transition error)CanTransitionTo(newState)— returnsboolAllowedTransitions— the set of valid target states from the current state
Usage in domain logic
Section titled “Usage in domain logic”public VoidResult<IError> Confirm(){ var result = TransitionTo(ReservationStatus.Confirmed); if (result.IsSuccess) { RaiseEvent(new ReservationConfirmed(Id, GuestId, PropertyId)); } return result;}Invalid transitions return a typed error rather than throwing — handle it like any other
Result failure. Because the transition graph is fixed at compile
time, adding a new state or edge is a one-line enum change, and any code path that would reach an
unreachable state simply cannot compile a valid TransitionTo for it.
Related
Section titled “Related”- Attributes —
[StateMachine<T>],[TransitionFrom],[InitialState] - Mutation Pipeline — where transitions run within a mutation
- Common Mistakes — transition pitfalls