SlimWorkFlowEngine 8.1.0
dotnet add package SlimWorkFlowEngine --version 8.1.0
NuGet\Install-Package SlimWorkFlowEngine -Version 8.1.0
<PackageReference Include="SlimWorkFlowEngine" Version="8.1.0" />
<PackageVersion Include="SlimWorkFlowEngine" Version="8.1.0" />
<PackageReference Include="SlimWorkFlowEngine" />
paket add SlimWorkFlowEngine --version 8.1.0
#r "nuget: SlimWorkFlowEngine, 8.1.0"
#:package SlimWorkFlowEngine@8.1.0
#addin nuget:?package=SlimWorkFlowEngine&version=8.1.0
#tool nuget:?package=SlimWorkFlowEngine&version=8.1.0
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 executionIWorkflow<TContext>- Interface for defining workflows containing multiple stepsIWorkflowStep<TContext>- Interface for individual workflow steps with result trackingBaseWorkflowContext- Strongly typed base context with error handling and metadataStepResult- 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
- Clone the repository
git clone https://github.com/slimbenbelgacem97/WorkFlowEngine.git
cd WorkFlowEngine
- Install dependencies
dotnet restore
- 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
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
| Product | Versions 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. |
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.Hosting (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
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+