SlimWorkFlowEngine 8.1.0

dotnet add package SlimWorkFlowEngine --version 8.1.0
                    
NuGet\Install-Package SlimWorkFlowEngine -Version 8.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SlimWorkFlowEngine" Version="8.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SlimWorkFlowEngine" Version="8.1.0" />
                    
Directory.Packages.props
<PackageReference Include="SlimWorkFlowEngine" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SlimWorkFlowEngine --version 8.1.0
                    
#r "nuget: SlimWorkFlowEngine, 8.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SlimWorkFlowEngine@8.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SlimWorkFlowEngine&version=8.1.0
                    
Install as a Cake Addin
#tool nuget:?package=SlimWorkFlowEngine&version=8.1.0
                    
Install as a Cake Tool

WorkFlow Engine

A powerful and flexible workflow orchestration engine for .NET 8+ that provides strongly typed contexts, conditional step execution, dynamic branching, and comprehensive result tracking.

Features

  • Strongly Typed Everything - Complete type safety with no dictionaries or loosely typed objects
  • Dynamic Step Execution - Conditional execution based on previous step results with intelligent dependency management
  • Workflow Branching - Steps can dynamically redirect workflow execution to different paths
  • Comprehensive Result Tracking - Detailed execution results with success/failure status, timing, and metadata
  • Rich Error Handling - Multi-level error tracking with severity classifications and detailed context
  • Quality Assurance Integration - Built-in QA steps with scoring and validation capabilities
  • Performance Metrics - Automatic tracking of execution timing, resource usage, and throughput
  • Fluent API - Intuitive method chaining for workflow configuration
  • Dependency Injection - Full DI container integration throughout the engine
  • Extensible Architecture - Easy to create custom workflows, steps, and contexts

Architecture Overview

The WorkFlow Engine is built around several core components:

Core Components

  • IWorkflowEngine - Main execution engine that orchestrates workflow execution
  • IWorkflow<TContext> - Interface for defining workflows containing multiple steps
  • IWorkflowStep<TContext> - Interface for individual workflow steps with result tracking
  • BaseWorkflowContext - Strongly typed base context with error handling and metadata
  • StepResult - Comprehensive result tracking for step execution

Key Concepts

  • Workflows - Orchestrate multiple steps in sequence or with conditional logic
  • Steps - Individual units of work that can execute conditionally based on previous results
  • Context - Strongly typed data container that flows through the entire workflow
  • Sub-workflows - Nested workflows for complex orchestration scenarios
  • Step Results - Detailed execution results with branching and continuation control

Enhanced StepResult Structure

public class StepResult
{
    public bool IsSuccess { get; set; }           // Execution success status
    public bool WasExecuted { get; set; }         // Whether step actually ran
    public bool ShouldContinue { get; set; }      // Workflow continuation control
    public string? NextStepOverride { get; set; } // Dynamic workflow branching
    public WorkflowError? Error { get; set; }     // Rich error information
    public object? Output { get; set; }           // Strongly typed step output
    public TimeSpan? Duration { get; set; }       // Execution timing
    public Dictionary<string, object> Metadata { get; set; } // Step metadata
}

Requirements

  • .NET 8.0 or later
  • Microsoft.Extensions.DependencyInjection 8.0+
  • Microsoft.Extensions.Logging 8.0+
  • Microsoft.Extensions.Hosting 8.0+

Installation

Package Manager

Install-Package SlimWorkFlowEngine

.NET CLI

dotnet add package SlimWorkFlowEngine

PackageReference

<PackageReference Include="SlimWorkFlowEngine" Version="8.1.0" />

?? Getting Started

1. Setup and Registration

using WorkFlowEngine;
using WorkFlowEngine.Core;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
        // Register workflow engine services
        services.AddWorkflowEngine();
        
        // Register your custom workflows and steps
        services.AddTransient<MyWorkflow>();
        services.AddTransient<MyValidationStep>();
        services.AddTransient<MyProcessingStep>();
        
        // Configure logging
        services.AddLogging(builder =>
        {
            builder.AddConsole();
            builder.SetMinimumLevel(LogLevel.Information);
        });
    })
    .Build();

2. Define Your Context

using WorkFlowEngine.Core;

public class MyWorkflowContext : BaseWorkflowContext
{
    public string InputData { get; set; } = string.Empty;
    public string ProcessedData { get; set; } = string.Empty;
    public bool IsDataValid { get; set; } = false;
    
    // Strongly typed results from specific steps
    public ValidationResults? ValidationResults { get; set; }
    public ProcessingResults? ProcessingResults { get; set; }

    // Step result collection from Core
    public StepResultCollection StepResults { get; } = new();
}

public class ValidationResults
{
    public bool IsValid { get; set; }
    public double QualityScore { get; set; }
    public string DataType { get; set; } = string.Empty;
    public List<string> Issues { get; set; } = new();
}

3. Create Custom Steps

using WorkFlowEngine.Core;

public class MyValidationStep : BaseWorkflowStep<MyWorkflowContext>
{
    public override string Name => "Validation";

    protected override async Task<StepResult> ExecuteStepWithResultAsync(
        MyWorkflowContext context, CancellationToken cancellationToken)
    {
        // Perform validation logic
        var results = await ValidateDataAsync(context.InputData);
        
        if (!results.IsValid)
        {
            return StepResult.Failure(
                stepName: Name,
                message: "Validation failed",
                shouldContinue: false  // Stop workflow on critical failure
            ).SetOutput(results);
        }
        
        // Dynamic branching based on quality
        var nextStep = results.QualityScore > 0.8 
            ? "AdvancedProcessing" 
            : "BasicProcessing";
        
        return StepResult.Success(
            stepName: Name,
            message: $"Validation passed with {results.QualityScore:P2} quality",
            nextStepOverride: nextStep
        ).SetOutput(results);
    }
}

4. Build Workflows

public class MyWorkflow : BaseWorkflow<MyWorkflowContext>
{
    public MyWorkflow(IServiceProvider serviceProvider) : base(serviceProvider)
    {
        ConfigureSteps();
    }

    public override string Name => "MyDataProcessingWorkflow";

    private void ConfigureSteps()
    {
        this.AddStep<MyValidationStep>()
            .AddStep<MyProcessingStep>()
            .AddStep<MyQualityAssuranceStep>()
            .AddStep<MyResultStep>();
    }
}

5. Execute Workflows

// Get services
var engine = host.Services.GetRequiredService<IWorkflowEngine>();
var workflow = host.Services.GetRequiredService<MyWorkflow>();

// Create context with input data
var context = new MyWorkflowContext
{
    InputData = "Sample data to process"
};

// Execute workflow
await engine.ExecuteWorkflowAsync(workflow, context);

// Analyze results
foreach (var stepResult in context.StepResults.All)
{
    Console.WriteLine($"{stepResult.StepName}: {stepResult}");
    
    if (stepResult.ShouldBranch)
    {
        Console.WriteLine($"  ? Branched to: {stepResult.NextStepOverride}");
    }
    
    if (stepResult.HasOutput)
    {
        Console.WriteLine($"  ? Output: {stepResult.Output?.GetType().Name}");
    }
}

Configuration

Workflow Configuration

Configure workflows for different scenarios:

public class DataProcessingWorkflow : BaseWorkflow<DataProcessingContext>
{
    public DataProcessingWorkflow ConfigureForScenario(string scenario)
    {
        ClearSteps();
        
        switch (scenario.ToLowerInvariant())
        {
            case "basic":
                this.AddStep<ValidateDataStep>()
                    .AddStep<ProcessDataStep>()
                    .AddStep<ResultStep>();
                break;
                
            case "advanced":
                this.AddStep<ValidateDataStep>()
                    .AddStep<ProcessDataStep>()
                    .AddStep<AdvancedProcessingStep>()
                    .AddStep<QualityAssuranceStep>()
                    .AddStep<ResultStep>();
                break;
        }
        
        return this;
    }
}

Service Registration

services.AddWorkflowEngine(options =>
{
    options.EnablePerformanceTracking = true;
    options.EnableDetailedLogging = true;
    options.DefaultTimeout = TimeSpan.FromMinutes(30);
});

Extensibility

Creating Custom Steps

Implement the BaseWorkflowStep<TContext> class:

using WorkFlowEngine.Core;

public class CustomProcessingStep : BaseWorkflowStep<MyWorkflowContext>
{
    private readonly IMyService _myService;

    public CustomProcessingStep(IMyService myService)
    {
        _myService = myService;
    }

    public override string Name => "CustomProcessing";

    // Conditional execution
    public override bool ShouldExecute(MyWorkflowContext context)
    {
        return base.ShouldExecute(context) && 
               IsPreviousStepSuccessful(context, "Validation");
    }

    protected override async Task<StepResult> ExecuteStepWithResultAsync(
        MyWorkflowContext context, CancellationToken cancellationToken)
    {
        try
        {
            var result = await _myService.ProcessAsync(context.InputData);
            
            return StepResult.Success(Name, "Processing completed")
                   .SetOutput(result)
                   .AddMetadata("ProcessingTime", DateTime.UtcNow)
                   .AddMetadata("ItemsProcessed", result.ItemCount);
        }
        catch (Exception ex)
        {
            return StepResult.Failure(Name, 
                new WorkflowError 
                { 
                    StepName = Name, 
                    Message = ex.Message, 
                    Exception = ex 
                });
        }
    }
}

Creating Custom Workflows

Extend BaseWorkflow<TContext>:

public class CustomWorkflow : BaseWorkflow<MyWorkflowContext>
{
    public CustomWorkflow(IServiceProvider serviceProvider) : base(serviceProvider)
    {
        ConfigureSteps();
    }

    public override string Name => "CustomWorkflow";

    private void ConfigureSteps()
    {
        this.AddStep<Step1>()
            .AddStep<Step2>()
            .AddStep<Step3>();
    }

    protected override async Task OnWorkflowStartAsync(MyWorkflowContext context, CancellationToken cancellationToken)
    {
        // Custom initialization logic
        context.StartTime = DateTime.UtcNow;
        await base.OnWorkflowStartAsync(context, cancellationToken);
    }

    protected override async Task OnWorkflowCompletedAsync(MyWorkflowContext context, CancellationToken cancellationToken)
    {
        // Custom completion logic
        context.EndTime = DateTime.UtcNow;
        await base.OnWorkflowCompletedAsync(context, cancellationToken);
    }
}

Sub-workflows

Create nested workflow execution:

public class ParentWorkflow : BaseWorkflow<MyWorkflowContext>
{
    private void ConfigureSteps()
    {
        this.AddStep<PreProcessingStep>()
            .AddStep<SubWorkflowStep<ChildWorkflow, MyWorkflowContext>>()
            .AddStep<PostProcessingStep>();
    }
}

Advanced Features

Dynamic Branching

Steps can redirect workflow execution:

protected override async Task<StepResult> ExecuteStepWithResultAsync(
    MyWorkflowContext context, CancellationToken cancellationToken)
{
    var qualityScore = AnalyzeQuality(context.Data);
    
    // Branch to different paths based on quality
    var nextStep = qualityScore switch
    {
        > 0.9 => "PremiumProcessing",
        > 0.7 => "StandardProcessing",
        > 0.4 => "BasicProcessing",
        _ => "ErrorHandling"
    };
    
    return StepResult.Success(Name, $"Quality: {qualityScore:P2}")
           .SetOutput(new QualityAnalysis { Score = qualityScore })
           .AddMetadata("QualityScore", qualityScore)
           .WithNextStepOverride(nextStep);
}

Continuation Control

Fine-grained control over workflow execution:

// Continue workflow despite step failure
return StepResult.Failure(Name, error, shouldContinue: true);

// Stop workflow on critical failure
return StepResult.Failure(Name, error, shouldContinue: false);

// Continue with warning
var result = StepResult.Success(Name, "Completed with warnings");
result.Error = warningError;  // Include warning details
return result;

Type-Safe Data Passing

Pass strongly typed data between steps:

// In ValidationStep
return StepResult.Success(Name).SetOutput(new ValidationResults 
{ 
    IsValid = true, 
    QualityScore = 0.95 
});

// In ProcessingStep
var validationData = GetPreviousStepOutput<ValidationResults>(context, "Validation");
if (validationData?.QualityScore > 0.8)
{
    // Apply advanced processing
}

Error Handling

Error Severity Levels

public enum WorkflowErrorSeverity
{
    Info,      // Informational messages
    Warning,   // Warnings that don't stop execution
    Error,     // Errors that may stop current step
    Critical   // Critical errors that stop entire workflow
}

Rich Error Context

var error = new WorkflowError
{
    StepName = Name,
    Message = "Processing failed",
    Exception = ex,
    Severity = WorkflowErrorSeverity.Error,
    Timestamp = DateTime.UtcNow
};

context.AddError(Name, "Step failed", ex, WorkflowErrorSeverity.Error);

Error Recovery

protected override async Task<StepResult> ExecuteStepWithResultAsync(
    MyWorkflowContext context, CancellationToken cancellationToken)
{
    try
    {
        var result = await ProcessDataAsync(context.InputData);
        return StepResult.Success(Name).SetOutput(result);
    }
    catch (RecoverableException ex)
    {
        // Continue with fallback processing
        var fallbackResult = await FallbackProcessAsync(context.InputData);
        return StepResult.Success(Name, "Completed with fallback")
               .SetOutput(fallbackResult)
               .WithNextStepOverride("QualityCheck");
    }
    catch (CriticalException ex)
    {
        // Stop entire workflow
        return StepResult.Failure(Name, CreateError(ex), shouldContinue: false);
    }
}

Testing

Unit Testing Steps

[Test]
public async Task ValidationStep_ValidData_ReturnsSuccess()
{
    // Arrange
    var step = new ValidationStep(_mockLogger.Object);
    var context = new MyWorkflowContext { InputData = "valid data" };

    // Act
    var result = await step.ExecuteStepWithResultAsync(context, CancellationToken.None);

    // Assert
    Assert.IsTrue(result.IsSuccess);
    Assert.IsTrue(result.WasExecuted);
    Assert.IsNotNull(result.GetOutput<ValidationResults>());
}

Integration Testing Workflows

[Test]
public async Task MyWorkflow_ValidInput_CompletesSuccessfully()
{
    // Arrange
    var engine = _serviceProvider.GetRequiredService<IWorkflowEngine>();
    var workflow = _serviceProvider.GetRequiredService<MyWorkflow>();
    var context = new MyWorkflowContext { InputData = "test data" };

    // Act
    await engine.ExecuteWorkflowAsync(workflow, context);

    // Assert
    Assert.IsTrue(context.StepResults.All(s => s.IsSuccess));
    Assert.AreEqual(4, context.StepResults.TotalCount);
}

Contributing

We welcome contributions! Please follow these guidelines:

Development Setup

  1. Clone the repository
git clone https://github.com/slimbenbelgacem97/WorkFlowEngine.git
cd WorkFlowEngine
  1. Install dependencies
dotnet restore
  1. Run tests
dotnet test

Contribution Guidelines

  • Follow C# coding conventions and best practices
  • Maintain backward compatibility when possible
  • Add comprehensive unit tests for new features
  • Update documentation for any public API changes
  • Ensure all builds pass before submitting PRs

Pull Request Process

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.1.0 705 9/23/2025

Initial release of SlimWorkFlowEngine - A comprehensive workflow orchestration engine for .NET 8+