WorkflowForge API Reference
Complete API reference for WorkflowForge core types and abstractions.
Table of Contents
- Core Factory
- Workflow Interfaces
- Operation Interfaces
- Foundry Interfaces
- Smith Interfaces
- Event Interfaces
- Testing Support
- Extension Interfaces
Core Factory
WorkflowForge
The main entry point for creating workflows and components.
public static class WorkflowForge
Methods
CreateWorkflow
public static WorkflowBuilder CreateWorkflow(string? workflowName = null, IServiceProvider? serviceProvider = null)
Creates a new workflow builder for fluent workflow construction.
Parameters:
workflowName: Optional workflow name (null lets you callWithNamelater)serviceProvider: Optional DI container for operation resolution
Returns: WorkflowBuilder for fluent configuration
Example:
var workflow = WorkflowForge.CreateWorkflow("OrderProcessing")
.AddOperation(new ValidateOperation())
.Build();
CreateFoundry
public static IWorkflowFoundry CreateFoundry(
string workflowName,
IWorkflowForgeLogger? logger = null,
IDictionary<string, object?>? initialProperties = null,
WorkflowForgeOptions? options = null)
Creates a new foundry (execution context) for workflow operations.
Parameters:
workflowName: Foundry name for identificationlogger: Optional logger for the foundryinitialProperties: Optional initial properties for the foundryoptions: Optional execution options for the foundry
Returns: IWorkflowFoundry execution context
Example:
using var foundry = WorkflowForge.CreateFoundry("MyFoundry", logger, initialProperties, options);
CreateSmith
public static IWorkflowSmith CreateSmith(
IWorkflowForgeLogger? logger = null,
IServiceProvider? serviceProvider = null,
WorkflowForgeOptions? options = null)
Creates a new smith (workflow executor).
Returns: IWorkflowSmith workflow executor
Example:
using var smith = WorkflowForge.CreateSmith();
await smith.ForgeAsync(workflow, foundry);
Workflow Interfaces
IWorkflow
Represents an immutable workflow definition.
public interface IWorkflow
{
Guid Id { get; }
string Name { get; }
string? Description { get; }
string Version { get; }
IReadOnlyList<IWorkflowOperation> Operations { get; }
bool SupportsRestore { get; }
}
Properties:
Id: Unique identifier for the workflowName: Human-readable workflow nameDescription: Optional description for documentationVersion: Workflow version stringOperations: Ordered collection of operations to executeSupportsRestore: Whether any operation supports compensation
WorkflowBuilder
Fluent builder for constructing workflows.
public sealed class WorkflowBuilder
{
WorkflowBuilder WithName(string name);
WorkflowBuilder WithDescription(string? description);
WorkflowBuilder WithVersion(string version);
WorkflowBuilder AddOperation(IWorkflowOperation operation);
WorkflowBuilder AddOperation<T>() where T : class, IWorkflowOperation;
WorkflowBuilder AddOperation(string name, Func<IWorkflowFoundry, CancellationToken, Task> action);
WorkflowBuilder AddOperation(string name, Action<IWorkflowFoundry> action);
WorkflowBuilder AddOperations(params IWorkflowOperation[] operations);
WorkflowBuilder AddOperations(IEnumerable<IWorkflowOperation> operations);
WorkflowBuilder AddParallelOperations(params IWorkflowOperation[] operations);
WorkflowBuilder AddParallelOperations(IEnumerable<IWorkflowOperation> operations, int? maxConcurrency = null, TimeSpan? timeout = null, string? name = null);
IWorkflow Build();
}
Notes:
AddOperation<T>()resolves the operation from the providedIServiceProvider.- Inline operations are wrapped into
ActionWorkflowOperationinstances. AddOperations()adds multiple operations to the sequential execution chain.AddParallelOperations()wraps operations in aForEachWorkflowOperationfor parallel execution with shared input.
Operation Interfaces
IWorkflowOperation
Base interface for all workflow operations.
public interface IWorkflowOperation : IDisposable
{
Guid Id { get; }
string Name { get; }
bool SupportsRestore { get; }
Task<object?> ForgeAsync(
object? inputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
Task RestoreAsync(
object? outputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
}
Properties:
Id: Unique identifier for the operation instanceName: Human-readable operation nameSupportsRestore: Whether operation implements compensation logic
Methods:
ForgeAsync
Task<object?> ForgeAsync(
object? inputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default)
Executes the operation’s main logic.
Parameters:
inputData: Optional input data (prefer foundry properties)foundry: Execution context providing services, logging, and propertiescancellationToken: Cancellation token
Returns: Operation result (optional)
Best Practice: Read from and write to foundry.Properties using SetProperty/GetPropertyOrDefault helpers instead of relying on inputData/return values.
RestoreAsync
Task RestoreAsync(
object? outputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default)
Executes compensation logic to undo operation effects.
Parameters:
outputData: Output from originalForgeAsynccallfoundry: Execution contextcancellationToken: Cancellation token
Usage: Called automatically by WorkflowSmith if workflow fails and SupportsRestore is true.
WorkflowOperationBase
Abstract base class implementing common operation patterns with lifecycle hooks.
public abstract class WorkflowOperationBase : IWorkflowOperation
{
public virtual Guid Id { get; } = Guid.NewGuid();
public abstract string Name { get; }
public virtual bool SupportsRestore => false;
// Lifecycle hooks (virtual, override to customize)
protected virtual Task OnBeforeExecuteAsync(object? inputData, IWorkflowFoundry foundry, CancellationToken ct)
=> Task.CompletedTask;
protected virtual Task OnAfterExecuteAsync(object? inputData, object? outputData, IWorkflowFoundry foundry, CancellationToken ct)
=> Task.CompletedTask;
// Core logic (abstract, implement in derived classes)
protected abstract Task<object?> ForgeAsyncCore(
object? inputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken);
// Public entry point (orchestrates hooks + core logic)
public Task<object?> ForgeAsync(
object? inputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
public virtual Task RestoreAsync(
object? outputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
public virtual void Dispose() { }
}
Features:
- Auto-generates unique
Idfor each operation instance - Default
SupportsRestore = false(override to enable compensation) RestoreAsyncthrowsNotSupportedExceptionifSupportsRestoreis false- Override
Dispose()if your operation holds unmanaged resources
Lifecycle Hooks (new in v2.0):
OnBeforeExecuteAsync: Called before the operation executes (setup, validation, logging)OnAfterExecuteAsync: Called after the operation completes successfully (cleanup, metrics)- Implement
ForgeAsyncCoreinstead ofForgeAsyncfor your operation logic
Example with Hooks:
public class AuditedOperation : WorkflowOperationBase
{
public override string Name => "AuditedOperation";
protected override Task OnBeforeExecuteAsync(object? inputData, IWorkflowFoundry foundry, CancellationToken ct)
{
foundry.Logger.LogInformation("Starting operation with input: {Input}", inputData);
return Task.CompletedTask;
}
protected override async Task<object?> ForgeAsyncCore(object? inputData, IWorkflowFoundry foundry, CancellationToken ct)
{
// Your operation logic here
return await ProcessAsync(inputData, ct);
}
protected override Task OnAfterExecuteAsync(object? inputData, object? outputData, IWorkflowFoundry foundry, CancellationToken ct)
{
foundry.Logger.LogInformation("Completed operation with result: {Output}", outputData);
return Task.CompletedTask;
}
}
Recommended Base Class: Use WorkflowOperationBase for most operations.
IWorkflowOperation<TInput, TOutput>
Generic interface for type-safe operations (advanced use case).
public interface IWorkflowOperation<TInput, TOutput> : IWorkflowOperation
{
Task<TOutput> ForgeAsync(
TInput input,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
Task RestoreAsync(
TOutput output,
IWorkflowFoundry foundry,
CancellationToken cancellationToken = default);
}
Use Case: When you need strongly-typed input/output contracts.
Note: Most operations should use WorkflowOperationBase with foundry properties instead.
Foundry Interfaces
IWorkflowFoundry
Execution context providing services, state, and logging to operations.
public interface IWorkflowFoundry :
IWorkflowExecutionContext,
IWorkflowMiddlewarePipeline,
IOperationLifecycleEvents,
IDisposable
{
Task ForgeAsync(CancellationToken cancellationToken = default);
void ReplaceOperations(IEnumerable<IWorkflowOperation> operations);
bool IsFrozen { get; }
}
Properties:
ExecutionId: Unique identifier for this foundry executionCurrentWorkflow: Workflow being executed (or null)ServiceProvider: DI container for resolving operation dependenciesLogger: Logging abstractionOptions: Execution options for the foundryProperties: Thread-safe dictionary for workflow dataIsFrozen: True whileForgeAsyncis executing (pipeline is immutable)
Notes:
- Property helpers like
SetProperty,GetPropertyOrDefault, andTryGetPropertyare extension methods. - Operations and middleware cannot be added/removed while
ForgeAsyncis running.
IWorkflowMiddlewarePipeline
Pipeline builder for operations and middleware.
public interface IWorkflowMiddlewarePipeline
{
void AddOperation(IWorkflowOperation operation);
void AddMiddleware(IWorkflowOperationMiddleware middleware);
void AddMiddlewares(IEnumerable<IWorkflowOperationMiddleware> middlewares);
}
Smith Interfaces
IWorkflowSmith
Workflow executor responsible for orchestrating operation execution.
public interface IWorkflowSmith :
IWorkflowLifecycleEvents,
ICompensationLifecycleEvents,
IDisposable
{
Task ForgeAsync(IWorkflow workflow, CancellationToken cancellationToken = default);
Task ForgeAsync(IWorkflow workflow, ConcurrentDictionary<string, object?> data, CancellationToken cancellationToken = default);
Task ForgeAsync(IWorkflow workflow, IWorkflowFoundry foundry, CancellationToken cancellationToken = default);
IWorkflowFoundry CreateFoundry(IWorkflowForgeLogger? logger = null, IServiceProvider? serviceProvider = null);
IWorkflowFoundry CreateFoundryFor(IWorkflow workflow, IWorkflowForgeLogger? logger = null, IServiceProvider? serviceProvider = null);
IWorkflowFoundry CreateFoundryWithData(ConcurrentDictionary<string, object?> data, IWorkflowForgeLogger? logger = null, IServiceProvider? serviceProvider = null);
void AddWorkflowMiddleware(IWorkflowMiddleware middleware);
}
Methods:
ForgeAsync(...): Executes a workflow using one of the three patterns (smith-managed, data dictionary, or reusable foundry).CreateFoundry(...): Creates a reusable foundry with optional logger/service provider.CreateFoundryFor(...): Creates a foundry pre-associated with a workflow.CreateFoundryWithData(...): Creates a foundry with an initial data dictionary.AddWorkflowMiddleware(...): Adds workflow-level middleware around the entire execution.
Example:
using var smith = WorkflowForge.CreateSmith();
using var foundry = smith.CreateFoundryFor(workflow);
await smith.ForgeAsync(workflow, foundry);
Event Interfaces
IWorkflowLifecycleEvents
Workflow-level lifecycle events.
public interface IWorkflowLifecycleEvents
{
event EventHandler<WorkflowStartedEventArgs>? WorkflowStarted;
event EventHandler<WorkflowCompletedEventArgs>? WorkflowCompleted;
event EventHandler<WorkflowFailedEventArgs>? WorkflowFailed;
}
Implemented By: IWorkflowSmith
Events:
WorkflowStarted: Fired before first operation executesWorkflowCompleted: Fired after all operations complete successfullyWorkflowFailed: Fired when workflow execution fails
Example:
smith.WorkflowStarted += (s, e) =>
Console.WriteLine($"Started: {e.WorkflowName}");
smith.WorkflowCompleted += (s, e) =>
Console.WriteLine($"Completed in {e.Duration.TotalMilliseconds}ms");
IOperationLifecycleEvents
Operation-level lifecycle events.
public interface IOperationLifecycleEvents
{
event EventHandler<OperationStartedEventArgs>? OperationStarted;
event EventHandler<OperationCompletedEventArgs>? OperationCompleted;
event EventHandler<OperationFailedEventArgs>? OperationFailed;
}
Implemented By: IWorkflowFoundry
Events:
OperationStarted: Fired before each operation executesOperationCompleted: Fired after operation completes successfullyOperationFailed: Fired when operation execution fails
Example:
foundry.OperationStarted += (s, e) =>
Console.WriteLine($"Operation {e.OperationName} started");
foundry.OperationCompleted += (s, e) =>
Console.WriteLine($"Operation {e.OperationName} completed");
ICompensationLifecycleEvents
Compensation (saga pattern) lifecycle events.
public interface ICompensationLifecycleEvents
{
event EventHandler<CompensationTriggeredEventArgs>? CompensationTriggered;
event EventHandler<CompensationCompletedEventArgs>? CompensationCompleted;
event EventHandler<OperationRestoreStartedEventArgs>? OperationRestoreStarted;
event EventHandler<OperationRestoreCompletedEventArgs>? OperationRestoreCompleted;
event EventHandler<OperationRestoreFailedEventArgs>? OperationRestoreFailed;
}
Implemented By: IWorkflowSmith
Events:
CompensationTriggered: Fired when workflow failure triggers compensationCompensationCompleted: Fired after all compensations completeOperationRestoreStarted: Fired before each operation’sRestoreAsyncOperationRestoreCompleted: Fired after successful restorationOperationRestoreFailed: Fired when restoration fails
Example:
smith.CompensationTriggered += (s, e) =>
Console.WriteLine($"Compensating {e.OperationsToCompensate} operations");
smith.OperationRestoreStarted += (s, e) =>
Console.WriteLine($"Rolling back {e.OperationName}");
Core Options
public sealed class WorkflowForgeOptions : WorkflowForgeOptionsBase
{
public bool Enabled { get; set; } = true;
public string SectionName { get; }
public int MaxConcurrentWorkflows { get; set; } = 0;
public bool ContinueOnError { get; set; } = false;
public bool FailFastCompensation { get; set; } = false;
public bool ThrowOnCompensationError { get; set; } = false;
public bool EnableOutputChaining { get; set; } = true;
public override IList<string> Validate();
public override object Clone();
}
Notes:
WorkflowForgeOptionsinherits fromWorkflowForgeOptionsBasefor consistentEnabled,SectionName,Validate(), andClone()behavior.
Testing Support
FakeWorkflowFoundry
A lightweight fake implementation of IWorkflowFoundry for unit testing operations.
Package: WorkflowForge.Testing
public class FakeWorkflowFoundry : IWorkflowFoundry
{
// Configurable properties
public Guid ExecutionId { get; set; }
public ConcurrentDictionary<string, object?> Properties { get; }
public IWorkflowForgeLogger Logger { get; set; }
public WorkflowForgeOptions Options { get; set; }
public IServiceProvider? ServiceProvider { get; set; }
// Test assertions
public IReadOnlyList<IWorkflowOperation> Operations { get; }
public IReadOnlyList<IWorkflowOperationMiddleware> Middlewares { get; }
public IReadOnlyList<IWorkflowOperation> ExecutedOperations { get; }
// Test helpers
public void Reset();
public void TrackExecution(IWorkflowOperation operation);
}
Features:
- Implements full
IWorkflowFoundryinterface - Tracks executed operations for assertions
- Configurable logger, options, and service provider
Reset()method for reusing between tests
Example Usage:
[Fact]
public async Task MyOperation_Should_SetProperty()
{
// Arrange
var foundry = new FakeWorkflowFoundry();
var operation = new MyCustomOperation();
// Act
await operation.ForgeAsync("input", foundry, CancellationToken.None);
// Assert
Assert.True(foundry.Properties.ContainsKey("myKey"));
Assert.Equal("expectedValue", foundry.Properties["myKey"]);
}
[Fact]
public async Task Workflow_Should_ExecuteAllOperations()
{
// Arrange
var foundry = new FakeWorkflowFoundry();
foundry.AddOperation(new StepOneOperation());
foundry.AddOperation(new StepTwoOperation());
// Act
await foundry.ForgeAsync();
// Assert
Assert.Equal(2, foundry.ExecutedOperations.Count);
}
Extension Interfaces
IWorkflowOperationMiddleware
Middleware for operation execution pipeline.
public interface IWorkflowOperationMiddleware
{
Task<object?> ExecuteAsync(
IWorkflowOperation operation,
IWorkflowFoundry foundry,
object? inputData,
Func<CancellationToken, Task<object?>> next,
CancellationToken cancellationToken);
}
Methods:
ExecuteAsync
Task<object?> ExecuteAsync(
IWorkflowOperation operation,
IWorkflowFoundry foundry,
object? inputData,
Func<CancellationToken, Task<object?>> next,
CancellationToken cancellationToken)
Executes middleware logic in the operation pipeline.
Parameters:
operation: Operation being executedfoundry: Execution contextnext: Delegate to call next middleware/operationcancellationToken: Cancellation token
Returns: Operation result
Example:
public class TimingMiddleware : IWorkflowOperationMiddleware
{
public async Task<object?> ExecuteAsync(
IWorkflowOperation operation,
IWorkflowFoundry foundry,
object? inputData,
Func<CancellationToken, Task<object?>> next,
CancellationToken cancellationToken)
{
var sw = Stopwatch.StartNew();
try
{
return await next(cancellationToken);
}
finally
{
sw.Stop();
_logger.LogInformation("Operation {Op} took {Ms}ms",
operation.Name, sw.ElapsedMilliseconds);
}
}
}
IWorkflowForgeLogger
Logging abstraction for framework and operations.
public interface IWorkflowForgeLogger
{
void LogTrace(string message, params object[] args);
void LogDebug(string message, params object[] args);
void LogInformation(string message, params object[] args);
void LogWarning(string message, params object[] args);
void LogError(Exception? exception, string message, params object[] args);
void LogCritical(Exception? exception, string message, params object[] args);
}
Methods: Standard logging levels (Trace, Debug, Information, Warning, Error, Critical)
Implementations:
ConsoleLogger: Default implementation (console output)NullLogger: No-op loggerSerilogAdapter: Bridges to Serilog (Extension)
ISystemTimeProvider
Time abstraction for testability.
public interface ISystemTimeProvider
{
DateTimeOffset UtcNow { get; }
}
Purpose: Enables time mocking in tests
Implementations:
SystemTimeProvider: ReturnsDateTimeOffset.UtcNow- Mock implementations for testing
Example:
public class TimeSensitiveOperation : WorkflowOperationBase
{
private readonly ISystemTimeProvider _timeProvider;
public TimeSensitiveOperation(ISystemTimeProvider timeProvider)
{
_timeProvider = timeProvider;
}
protected override async Task<object?> ForgeAsyncCore(
object? inputData,
IWorkflowFoundry foundry,
CancellationToken cancellationToken)
{
var now = _timeProvider.UtcNow;
// Time-dependent logic
return inputData;
}
}
Built-In Operations
DelayOperation
Introduces a delay in workflow execution.
public class DelayOperation : WorkflowOperationBase
{
public DelayOperation(TimeSpan delay);
}
Example:
var workflow = WorkflowForge.CreateWorkflow("DelayedWorkflow")
.AddOperation(new DelayOperation(TimeSpan.FromSeconds(2)))
.Build();
LoggingOperation
Logs a message during workflow execution.
public class LoggingOperation : WorkflowOperationBase
{
public LoggingOperation(IWorkflowForgeLogger logger, string message);
}
Example:
var workflow = WorkflowForge.CreateWorkflow("LoggingWorkflow")
.AddOperation(new LoggingOperation(logger, "Starting workflow"))
.Build();
ConditionalWorkflowOperation
Executes different operations based on a predicate.
public class ConditionalWorkflowOperation : WorkflowOperationBase
{
public ConditionalWorkflowOperation(
Func<IWorkflowFoundry, bool> predicate,
IWorkflowOperation trueOperation,
IWorkflowOperation falseOperation);
}
Example:
var conditionalOp = new ConditionalWorkflowOperation(
predicate: f => f.GetPropertyOrDefault<decimal>("Amount") > 100,
trueOperation: new HighValueOperation(),
falseOperation: new StandardOperation());
ForEachWorkflowOperation
Executes multiple operations concurrently with configurable data distribution.
public sealed class ForEachWorkflowOperation : WorkflowOperationBase
{
// Factory methods
public static ForEachWorkflowOperation CreateSharedInput(
IEnumerable<IWorkflowOperation> operations,
TimeSpan? timeout = null,
int? maxConcurrency = null,
string? name = null);
public static ForEachWorkflowOperation CreateSplitInput(
IEnumerable<IWorkflowOperation> operations,
TimeSpan? timeout = null,
int? maxConcurrency = null,
string? name = null);
public static ForEachWorkflowOperation CreateNoInput(
IEnumerable<IWorkflowOperation> operations,
TimeSpan? timeout = null,
int? maxConcurrency = null,
string? name = null);
}
Data Strategies:
CreateSharedInput: All operations receive the same input dataCreateSplitInput: Input collection is split and distributed among operationsCreateNoInput: Operations receive null input
Example:
// Execute multiple operations in parallel with shared input
var forEachOp = ForEachWorkflowOperation.CreateSharedInput(
new IWorkflowOperation[] { new ProcessA(), new ProcessB(), new ProcessC() },
maxConcurrency: 4,
name: "ProcessAll");
// Throttled execution with 2 concurrent operations max
var throttledOp = ForEachWorkflowOperation.CreateSplitInput(
operations,
maxConcurrency: 2);
Related Documentation
- Architecture - Understanding the design
- Operations - Creating operations
- Events - Event system details
- Configuration - Configuring workflows
- Extensions - Extension ecosystem