### Introspect State and Next Events Source: https://context7.com/masstransit/automatonymous/llms.txt Use GetState to retrieve the current state object of an instance and NextEvents to get a list of events that can be raised in the current state. ```csharp var machine = new OrderStateMachine(); var instance = new OrderState(); await machine.RaiseEvent(instance, machine.OrderSubmitted, new OrderSubmitted("ORD-42", 150m)); // Get current state object State current = await machine.GetState(instance); Console.WriteLine(current.Name); // "Submitted" // Get all events that are valid in the current state IEnumerable next = await machine.NextEvents(instance); foreach (var e in next) Console.WriteLine(e.Name); // "OrderCancelled", "OrderCompleted" ``` -------------------------------- ### Customize Unhandled Event Behavior Source: https://context7.com/masstransit/automatonymous/llms.txt Use OnUnhandledEvent to define custom behavior for events raised in states without a handler, preventing default exceptions. The example shows logging unhandled events. ```csharp public class SafeMachine : AutomatonymousStateMachine { public State Idle { get; private set; } public Event Ping { get; private set; } public Event Pong { get; private set; } public SafeMachine() { Initially(When(Ping).TransitionTo(Idle)); // Silently ignore unhandled events instead of throwing OnUnhandledEvent(ctx => { Console.WriteLine( $ ``` -------------------------------- ### Execute Activities on State Entry/Exit with Lifecycle Hooks Source: https://context7.com/masstransit/automatonymous/llms.txt Use WhenEnter, AfterLeaveAny, and BeforeEnterAny to execute activities when entering or leaving states. BeforeEnterAny receives the incoming state as data. ```csharp public class AuditedMachine : AutomatonymousStateMachine { public State Active { get; private set; } public State Inactive { get; private set; } public Event Activate { get; private set; } public Event Deactivate { get; private set; } public AuditedMachine() { Initially(When(Activate).TransitionTo(Active)); During(Active, When(Deactivate).TransitionTo(Inactive)); // Called when entering Active WhenEnter(Active, b => b.Then(ctx => Console.WriteLine($"Entered Active at {DateTime.UtcNow}"))); // Called when leaving any state; receives the next state as Data AfterLeaveAny(b => b.Then(ctx => Console.WriteLine($"Left state; next = {ctx.Data.Name}"))); // Called before entering any state; receives the incoming state as Data BeforeEnterAny(b => b.Then(ctx => Console.WriteLine($"About to enter {ctx.Data.Name}"))); } } ``` -------------------------------- ### Defining a State Machine — AutomatonymousStateMachine Source: https://context7.com/masstransit/automatonymous/llms.txt The primary entry point for defining a state machine. Subclass this to declare states, events, and transitions using a fluent DSL. ```APIDOC ## Defining a State Machine — AutomatonymousStateMachine The primary entry point. Subclass this to declare states, events, and transitions. The constructor uses the fluent DSL methods to wire everything together. State and event properties are auto-registered by reflection. ```csharp // Instance POCO — holds persisted state public class OrderState { public State CurrentState { get; set; } // or string / int public string OrderId { get; set; } public decimal Total { get; set; } } // Message / event data public record OrderSubmitted(string OrderId, decimal Total); public record OrderCancelled(string Reason); // State machine definition public class OrderStateMachine : AutomatonymousStateMachine { public State Submitted { get; private set; } public State Cancelled { get; private set; } public Event OrderSubmitted { get; private set; } public Event OrderCancelled { get; private set; } public Event OrderCompleted { get; private set; } public OrderStateMachine() { // Tell the machine which property stores state InstanceState(x => x.CurrentState); // Initial -> Submitted when OrderSubmitted is raised Initially( When(OrderSubmitted) .Then(ctx => { ctx.Instance.OrderId = ctx.Data.OrderId; ctx.Instance.Total = ctx.Data.Total; }) .TransitionTo(Submitted)); // In Submitted state, handle cancellation or completion During(Submitted, When(OrderCancelled) .Then(ctx => Console.WriteLine($"Cancelled: {ctx.Data.Reason}")) .TransitionTo(Cancelled), When(OrderCompleted) .Finalize()); // Once finalized, clean up Finally(b => b.Then(ctx => Console.WriteLine("Order finalized."))); SetCompletedWhenFinalized(); } } ``` ``` -------------------------------- ### Define Order State Machine Source: https://context7.com/masstransit/automatonymous/llms.txt Define a state machine for order processing, including states, events, and transitions. Use `InstanceState` to specify how the current state is persisted. ```csharp public class OrderState { public State CurrentState { get; set; } // or string / int public string OrderId { get; set; } public decimal Total { get; set; } } public record OrderSubmitted(string OrderId, decimal Total); public record OrderCancelled(string Reason); public class OrderStateMachine : AutomatonymousStateMachine { public State Submitted { get; private set; } public State Cancelled { get; private set; } public Event OrderSubmitted { get; private set; } public Event OrderCancelled { get; private set; } public Event OrderCompleted { get; private set; } public OrderStateMachine() { InstanceState(x => x.CurrentState); Initially( When(OrderSubmitted) .Then(ctx => { ctx.Instance.OrderId = ctx.Data.OrderId; ctx.Instance.Total = ctx.Data.Total; }) .TransitionTo(Submitted)); During(Submitted, When(OrderCancelled) .Then(ctx => Console.WriteLine($"Cancelled: {ctx.Data.Reason}")) .TransitionTo(Cancelled), When(OrderCompleted) .Finalize()); Finally(b => b.Then(ctx => Console.WriteLine("Order finalized."))); SetCompletedWhenFinalized(); } } ``` -------------------------------- ### Declare State Storage with InstanceState Source: https://context7.com/masstransit/automatonymous/llms.txt Configure which property on the instance POCO persists the current state. Supports `State`, `string`, or `int`. ```csharp public class PaymentState { public string CurrentState { get; set; } // stored as state name string public int StateIndex { get; set; } // stored as integer index } public class PaymentMachine : AutomatonymousStateMachine { public State Pending { get; private set; } public State Confirmed { get; private set; } public State Failed { get; private set; } public PaymentMachine() { InstanceState(x => x.CurrentState); InstanceState(x => x.StateIndex, Pending, Confirmed, Failed); } } ``` -------------------------------- ### Handle Events in All States and on Finalization Source: https://context7.com/masstransit/automatonymous/llms.txt Use DuringAny to bind event handlers for all non-initial, non-final states. Finally executes activities whenever the Final state is entered. ```csharp public class CleanupMachine : AutomatonymousStateMachine { public State Running { get; private set; } public State Paused { get; private set; } public Event Pause { get; private set; } public Event Resume { get; private set; } public Event Shutdown { get; private set; } public CleanupMachine() { Initially(When(Pause).TransitionTo(Paused)); During(Paused, When(Resume).TransitionTo(Running)); // Handle Shutdown in ALL non-terminal states DuringAny( When(Shutdown).Finalize()); // Always runs on Finalize, in any state Finally(b => b .ThenAsync(async ctx => await ReleaseResourcesAsync(ctx.Instance))); } } ``` -------------------------------- ### Chain Activities in Event Handlers Source: https://context7.com/masstransit/automatonymous/llms.txt Chains synchronous/async callbacks, state transitions, conditional branches, and exception handlers using methods like .Then, .If, and .Catch. ```csharp public class ProcessingMachine : AutomatonymousStateMachine { public State Processing { get; private set; } public State Failed { get; private set; } public State Done { get; private set; } public Event Start { get; private set; } public ProcessingMachine() { Initially( When(Start) // Synchronous action .Then(ctx => ctx.Instance.WorkId = ctx.Data.Id) // Async action .ThenAsync(async ctx => await SaveToDbAsync(ctx.Instance)) // Conditional branch .If(ctx => ctx.Data.Priority > 5, b => b.Then(ctx => ctx.Instance.IsHighPriority = true)) // Exception handling .Catch(ex => ex .Then(ctx => ctx.Instance.Error = ctx.Exception.Message) .TransitionTo(Failed)) .TransitionTo(Processing)); During(Processing, When(Start) // re-raise in this state is ignored or handled .If(ctx => ctx.Instance.IsHighPriority, b => b.TransitionTo(Done), b => b.Then(_ => Console.WriteLine("Still processing")))); } } ``` -------------------------------- ### Raise Events on State Machine Instances Source: https://context7.com/masstransit/automatonymous/llms.txt Dispatches events, with or without data, to drive a state machine instance forward. Supports direct event raising and selector lambdas. ```csharp var machine = new OrderStateMachine(); var instance = new OrderState(); // Raise a data event await machine.RaiseEvent(instance, machine.OrderSubmitted, new OrderSubmitted("ORD-001", 99.99m)); // Raise a trigger event (no data) await machine.RaiseEvent(instance, machine.OrderCompleted); // Using a selector lambda (avoids capturing machine reference separately) await machine.RaiseEvent(instance, m => m.OrderCancelled, new OrderCancelled("Customer request")); // Check resulting state var state = await machine.GetState(instance); Console.WriteLine(state.Name); // "Cancelled" ``` -------------------------------- ### Connect State and Event Observers Source: https://context7.com/masstransit/automatonymous/llms.txt Attach reactive observers using ConnectStateObserver and ConnectEventObserver to receive notifications on state changes or event executions. Returns an IDisposable to disconnect. ```csharp public class AuditStateObserver : StateObserver { public Task StateChanged(InstanceContext context, State currentState, State previousState) { Console.WriteLine( $"Transition: {previousState?.Name ?? "none"} -> {currentState.Name}"); return Task.CompletedTask; } } var machine = new OrderStateMachine(); var instance = new OrderState(); using var stateSubscription = machine.ConnectStateObserver(new AuditStateObserver()); using var eventSubscription = machine.ConnectEventObserver( machine.OrderSubmitted, new SelectedEventObserverAdapter()); await machine.RaiseEvent(instance, machine.OrderSubmitted, new OrderSubmitted("ORD-99", 200m)); // Console: Transition: none -> Submitted ``` -------------------------------- ### Generate State Machine Graph Source: https://context7.com/masstransit/automatonymous/llms.txt Generates a `StateMachineGraph` containing nodes and edges, suitable for rendering or documentation. This is useful for visualizing the state machine's structure. ```csharp var machine = new OrderStateMachine(); StateMachineGraph graph = machine.GetGraph(); Console.WriteLine("=== Vertices ==="); foreach (var vertex in graph.Vertices) Console.WriteLine($" [{vertex.VertexType}] {vertex.Title}"); Console.WriteLine("=== Edges ==="); foreach (var edge in graph.Edges) Console.WriteLine($" {edge.From.Title} --({edge.Title})--> {edge.To.Title}"); // Sample output: // === Vertices === // [State] Initial // [State] Submitted // [State] Cancelled // [State] Final // [Event] OrderSubmitted // [Event] OrderCancelled // [Event] OrderCompleted // === Edges === // Initial --( OrderSubmitted )--> Submitted // Submitted --( OrderCancelled )--> Cancelled // Submitted --( OrderCompleted )--> Final ``` -------------------------------- ### Builder Pattern for State Machine Source: https://context7.com/masstransit/automatonymous/llms.txt Constructs a state machine using the builder pattern without a named subclass, employing a modifier callback for configuration. This is useful for defining state machines inline. ```csharp var machine = AutomatonymousStateMachine.New(cfg => { var running = cfg.State("Running"); var stopped = cfg.State("Stopped"); var start = cfg.Event("Start"); var stop = cfg.Event("Stop"); cfg.InstanceState(x => x.CurrentState); cfg.Initially(cfg.When(start).TransitionTo(running)); cfg.During(running, cfg.When(stop).TransitionTo(stopped)); }); ``` -------------------------------- ### Declare States and Sub-States in Automatonymous Source: https://context7.com/masstransit/automatonymous/llms.txt Defines named states and sub-states for a state machine. Sub-states inherit event handlers from their parent states. ```csharp public class DocumentMachine : AutomatonymousStateMachine { public State Review { get; private set; } public State Approved { get; private set; } // Sub-states of Review public State PeerReview { get; private set; } public State LegalCheck { get; private set; } public Event Submit { get; private set; } public Event Approve { get; private set; } public DocumentMachine() { SubState(() => PeerReview, Review); SubState(() => LegalCheck, Review); Initially(When(Submit).TransitionTo(PeerReview)); During(Review, // applies to both PeerReview and LegalCheck When(Approve).TransitionTo(Approved)); } } ``` -------------------------------- ### Declaring State Storage — InstanceState Source: https://context7.com/masstransit/automatonymous/llms.txt Configures which property on the instance POCO persists the current state of the state machine. Supports `State`, `string`, or `int` representations. ```APIDOC ## Declaring State Storage — InstanceState Configures which property on `TInstance` persists the current state; supports `State`, `string`, or `int` representations. ```csharp public class PaymentState { public string CurrentState { get; set; } // stored as state name string public int StateIndex { get; set; } // stored as integer index } public class PaymentMachine : AutomatonymousStateMachine { public State Pending { get; private set; } public State Confirmed { get; private set; } public State Failed { get; private set; } public PaymentMachine() { // Option A: persist as string InstanceState(x => x.CurrentState); // Option B: persist as int (0=none, 1=Initial, 2=Final, 3+=custom order) // InstanceState(x => x.StateIndex, Pending, Confirmed, Failed); } } ``` ``` -------------------------------- ### Define Composite Events in Automatonymous Source: https://context7.com/masstransit/automatonymous/llms.txt Creates a composite event that fires only after all specified constituent events have been raised. Requires a tracking property on the state instance. ```csharp public class ShippingState { public State CurrentState { get; set; } public CompositeEventStatus ReadyStatus { get; set; } } public class ShippingMachine : AutomatonymousStateMachine { public State WaitingForReadiness { get; private set; } public State ReadyToShip { get; private set; } public Event PaymentReceived { get; private set; } public Event InventoryPicked { get; private set; } public Event AllReady { get; private set; } // composite public ShippingMachine() { // AllReady fires when BOTH PaymentReceived AND InventoryPicked have been raised CompositeEvent(() => AllReady, x => x.ReadyStatus, PaymentReceived, InventoryPicked); Initially(When(PaymentReceived).TransitionTo(WaitingForReadiness)); During(WaitingForReadiness, When(InventoryPicked).Then(_ => { /* acknowledge */ }), When(AllReady).TransitionTo(ReadyToShip)); } } ``` -------------------------------- ### Declare Events for State Machine Source: https://context7.com/masstransit/automatonymous/llms.txt Declare trigger events (no data) or data events (carry a typed payload) on the state machine. Properties are auto-initialized via reflection. ```csharp public class ShipmentMachine : AutomatonymousStateMachine { public Event Dispatched { get; private set; } public Event TrackingUpdated { get; private set; } public ShipmentMachine() { Initially( When(Dispatched).TransitionTo(InTransit)); During(InTransit, When(TrackingUpdated) .Then(ctx => ctx.Instance.Location = ctx.Data.Location)); } } ``` -------------------------------- ### Declaring Events — Event / Event Source: https://context7.com/masstransit/automatonymous/llms.txt Declares trigger events (no data) or data events (carry a typed payload) on the state machine. Properties are auto-initialized via reflection. ```APIDOC ## Declaring Events — Event / Event Declares trigger events (no data) or data events (carry a typed payload) on the machine. Properties are auto-registered via reflection; no explicit `Event(...)` call is required unless a dynamic name is needed. ```csharp public class ShipmentMachine : AutomatonymousStateMachine { // Trigger event — no payload public Event Dispatched { get; private set; } // Data event — carries typed payload public Event TrackingUpdated { get; private set; } public ShipmentMachine() { Initially( When(Dispatched).TransitionTo(InTransit)); During(InTransit, When(TrackingUpdated) .Then(ctx => ctx.Instance.Location = ctx.Data.Location)); } } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.