Skip to content

Source Generators

The Strategos.Generators package transforms fluent DSL definitions into type-safe artifacts at compile time.

ArtifactPurpose
Phase EnumType-safe enumeration of workflow phases
CommandsWolverine message types for step transitions
EventsMarten event types for audit trail
Saga ClassComplete Wolverine saga with handlers
State ReducersProperty merge logic based on attributes
DI ExtensionsService registration helpers

Generated enumeration representing all workflow phases.

For a workflow named process-order with steps ValidateOrder, ProcessPayment, FulfillOrder:

// Generated
public enum ProcessOrderPhase
{
NotStarted,
ValidateOrder,
ProcessPayment,
FulfillOrder,
Completed,
Failed
}
ValueDescription
NotStartedInitial state before workflow begins
CompletedTerminal state after successful completion
FailedTerminal state after failure

Generated Wolverine command types for triggering step execution.

// Generated for each step
public record ExecuteValidateOrderCommand(
[property: SagaIdentity] Guid WorkflowId);
public record ExecuteProcessPaymentCommand(
[property: SagaIdentity] Guid WorkflowId);
public record ExecuteFulfillOrderCommand(
[property: SagaIdentity] Guid WorkflowId);
AttributePurpose
[SagaIdentity]Links command to saga instance

Generated Marten event types for audit trail.

// Workflow lifecycle events
public record ProcessOrderWorkflowStarted(Guid WorkflowId, DateTimeOffset Timestamp);
public record ProcessOrderWorkflowCompleted(Guid WorkflowId, DateTimeOffset Timestamp);
// Phase transition events
public record ProcessOrderPhaseChanged(
Guid WorkflowId,
ProcessOrderPhase FromPhase,
ProcessOrderPhase ToPhase,
DateTimeOffset Timestamp);
// Step completion events
public record ValidateOrderStepCompleted(
Guid WorkflowId,
DateTimeOffset Timestamp,
OrderState StateSnapshot);
PropertyTypeDescription
WorkflowIdGuidWorkflow instance identifier
TimestampDateTimeOffsetWhen the event occurred
FromPhaseEnumPrevious phase (for transitions)
ToPhaseEnumNew phase (for transitions)
StateSnapshotTStateState at completion (for step events)

Generated Wolverine saga containing all handlers.

// Generated saga
public 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...
}
PropertyTypeDescription
WorkflowIdGuidSaga identity
StateTStateCurrent workflow state
PhaseEnumCurrent workflow phase

Generated logic for merging state updates based on attributes.

// For state with [Append] and [Merge] attributes
public 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)
};
}
}
AttributeBehavior
(none)Update replaces current
[Append]Lists are concatenated
[Merge]Dictionaries are combined, newer wins

Generated service registration helpers.

// Generated extension method
public 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 assembly
services.AddStrategos()
.AddWorkflowsFromAssembly(typeof(ProcessOrderWorkflow).Assembly);

Generation is triggered by the [Workflow] attribute on a class containing a workflow definition.

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>();
}
RequirementDescription
[Workflow] attributeTriggers source generation
partial modifierAllows generator to extend class
static modifierWorkflow definitions are static
NamespaceCannot be in global namespace

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. :::