Source Generators
Source Generators
Section titled “Source Generators”The Strategos.Generators package transforms fluent DSL definitions into type-safe artifacts at compile time.
Generated Artifacts Overview
Section titled “Generated Artifacts Overview”| Artifact | Purpose |
|---|---|
| Phase Enum | Type-safe enumeration of workflow phases |
| Commands | Wolverine message types for step transitions |
| Events | Marten event types for audit trail |
| Saga Class | Complete Wolverine saga with handlers |
| State Reducers | Property merge logic based on attributes |
| DI Extensions | Service registration helpers |
Phase Enum
Section titled “Phase Enum”Generated enumeration representing all workflow phases.
Generation Pattern
Section titled “Generation Pattern”For a workflow named process-order with steps ValidateOrder, ProcessPayment, FulfillOrder:
// Generatedpublic enum ProcessOrderPhase{ NotStarted, ValidateOrder, ProcessPayment, FulfillOrder, Completed, Failed}Special Values
Section titled “Special Values”| Value | Description |
|---|---|
NotStarted | Initial state before workflow begins |
Completed | Terminal state after successful completion |
Failed | Terminal state after failure |
Persistence
Section titled “Persistence”The saga document stores Phase as a name under System.Text.Json and as an ordinal under Newtonsoft. A member reorder (for example the document-order restore in 2.11.0) is safe only for the name representation. See Phase Enum Persistence.
Commands
Section titled “Commands”Generated Wolverine command types for triggering step execution.
Generation Pattern
Section titled “Generation Pattern”// Generated for each steppublic record ExecuteValidateOrderCommand( [property: SagaIdentity] Guid WorkflowId);
public record ExecuteProcessPaymentCommand( [property: SagaIdentity] Guid WorkflowId);
public record ExecuteFulfillOrderCommand( [property: SagaIdentity] Guid WorkflowId);Attributes
Section titled “Attributes”| Attribute | Purpose |
|---|---|
[SagaIdentity] | Links command to saga instance |
Events
Section titled “Events”Generated Marten event types for audit trail.
Generation Pattern
Section titled “Generation Pattern”// Workflow lifecycle eventspublic record ProcessOrderWorkflowStarted(Guid WorkflowId, DateTimeOffset Timestamp);public record ProcessOrderWorkflowCompleted(Guid WorkflowId, DateTimeOffset Timestamp);
// Phase transition eventspublic record ProcessOrderPhaseChanged( Guid WorkflowId, ProcessOrderPhase FromPhase, ProcessOrderPhase ToPhase, DateTimeOffset Timestamp);
// Step completion eventspublic record ValidateOrderStepCompleted( Guid WorkflowId, DateTimeOffset Timestamp, OrderState StateSnapshot);Event Properties
Section titled “Event Properties”| Property | Type | Description |
|---|---|---|
WorkflowId | Guid | Workflow instance identifier |
Timestamp | DateTimeOffset | When the event occurred |
FromPhase | Enum | Previous phase (for transitions) |
ToPhase | Enum | New phase (for transitions) |
StateSnapshot | TState | State at completion (for step events) |
Saga Class
Section titled “Saga Class”Generated Wolverine saga containing all handlers.
Generation Pattern
Section titled “Generation Pattern”// Generated sagapublic partial class ProcessOrderSaga : Saga{ public Guid WorkflowId { get; set; } public OrderState State { get; set; } public ProcessOrderPhase Phase { get; set; }
// Entry point public async Task<ExecuteValidateOrderCommand> Start( StartProcessOrderCommand command, CancellationToken ct) { WorkflowId = command.WorkflowId; State = command.InitialState; Phase = ProcessOrderPhase.ValidateOrder; return new ExecuteValidateOrderCommand(WorkflowId); }
// Step handlers public async Task<ExecuteProcessPaymentCommand> Handle( ExecuteValidateOrderCommand command, ValidateOrderStep step, CancellationToken ct) { var result = await step.ExecuteAsync(State, CreateContext(), ct); State = ProcessOrderStateReducer.Reduce(State, result.State); Phase = ProcessOrderPhase.ProcessPayment; return new ExecuteProcessPaymentCommand(WorkflowId); }
// Additional handlers...}Saga Properties
Section titled “Saga Properties”| Property | Type | Description |
|---|---|---|
WorkflowId | Guid | Saga identity |
State | TState | Current workflow state |
Phase | Enum | Current workflow phase |
State Reducers
Section titled “State Reducers”Generated logic for merging state updates based on attributes.
Generation Pattern
Section titled “Generation Pattern”// For state with [Append] and [Merge] attributespublic static class ProcessOrderStateReducer{ public static OrderState Reduce(OrderState current, OrderState update) { return current with { // Regular properties: take update value Status = update.Status ?? current.Status, TotalAmount = update.TotalAmount,
// [Append] properties: combine lists AuditLog = current.AuditLog .Concat(update.AuditLog ?? Enumerable.Empty<string>()) .ToList(),
// [Merge] properties: combine dictionaries Metadata = current.Metadata .Concat(update.Metadata ?? new()) .GroupBy(kv => kv.Key) .ToDictionary(g => g.Key, g => g.Last().Value) }; }}Merge Behaviors
Section titled “Merge Behaviors”| Attribute | Behavior |
|---|---|
| (none) | Update replaces current |
[Append] | Lists are concatenated |
[Merge] | Dictionaries are combined, newer wins |
DI Extensions
Section titled “DI Extensions”Generated service registration helpers.
Generation Pattern
Section titled “Generation Pattern”// Generated extension methodpublic static class ProcessOrderWorkflowExtensions{ public static IServiceCollection AddProcessOrderWorkflow( this IServiceCollection services) { // Register step implementations services.AddScoped<ValidateOrderStep>(); services.AddScoped<ProcessPaymentStep>(); services.AddScoped<FulfillOrderStep>();
// Register saga services.AddScoped<ProcessOrderSaga>();
return services; }}services.AddStrategos() .AddProcessOrderWorkflow();
// Or add all workflows in assemblyservices.AddStrategos() .AddWorkflowsFromAssembly(typeof(ProcessOrderWorkflow).Assembly);Triggering Generation
Section titled “Triggering Generation”Generation is triggered by the [Workflow] attribute on a class containing a workflow definition.
Required Pattern
Section titled “Required Pattern”using Strategos;
namespace MyApp.Workflows;
[Workflow("process-order")]public static partial class ProcessOrderWorkflow{ public static WorkflowDefinition<OrderState> Definition => Workflow<OrderState>.Create("process-order") .StartWith<ValidateOrderStep>() .Then<ProcessPaymentStep>() .Finally<FulfillOrderStep>();}Requirements
Section titled “Requirements”| Requirement | Description |
|---|---|
[Workflow] attribute | Triggers source generation |
partial modifier | Allows generator to extend class |
static modifier | Workflow definitions are static |
| Namespace | Cannot be in global namespace |
Generated File Location
Section titled “Generated File Location”Generated files appear in the obj directory and are visible in IDE under Dependencies > Analyzers:
obj/ Debug/ net8.0/ generated/ Strategos.Generators/ ProcessOrderWorkflow.g.cs ProcessOrderSaga.g.cs ProcessOrderStateReducer.g.cs::: tip Viewing Generated Code In Visual Studio, expand Dependencies > Analyzers > Strategos.Generators to see generated files. In Rider, use Navigate > Generated Code. :::