Zooper.Bee
2.2.0
See the version list below for details.
dotnet add package Zooper.Bee --version 2.2.0
NuGet\Install-Package Zooper.Bee -Version 2.2.0
<PackageReference Include="Zooper.Bee" Version="2.2.0" />
<PackageVersion Include="Zooper.Bee" Version="2.2.0" />
<PackageReference Include="Zooper.Bee" />
paket add Zooper.Bee --version 2.2.0
#r "nuget: Zooper.Bee, 2.2.0"
#addin nuget:?package=Zooper.Bee&version=2.2.0
#tool nuget:?package=Zooper.Bee&version=2.2.0
Zooper.Bee
<img src="icon.png" alt="Zooper.Bee Logo" width="120" align="right"/>
Zooper.Bee is a fluent, lightweight workflow framework for C# that enables you to build type-safe, declarative business workflows with robust error handling.
Key Features
- Fluent Builder API: Create workflows with an intuitive, chainable syntax
- Type-safe: Leverage C#'s static typing for error-resistant workflows
- Functional Style: Uses an Either monad pattern for clear success/failure handling
- Composable: Build complex workflows from simple, reusable components
- Comprehensive: Support for validations, conditional activities, branches, and finally blocks
- Isolated Branches: Create branches with their own isolated local payload types
- Async-first: First-class support for async/await operations
- Testable: Workflows built with Zooper.Bee are easy to unit test
- No Dependencies: Minimal external dependencies (only uses Zooper.Fox)
Installation
dotnet add package Zooper.Bee
Quick Start
Here's a basic example of creating and executing a workflow:
// Define your models
public record OrderRequest(string CustomerId, decimal Amount);
public record OrderPayload(OrderRequest Request, Guid OrderId, bool IsProcessed);
public record OrderConfirmation(Guid OrderId, DateTime ProcessedAt);
public record OrderError(string Code, string Message);
// Create a workflow
var workflow = new WorkflowBuilder<OrderRequest, OrderPayload, OrderConfirmation, OrderError>(
// Initial payload factory
request => new OrderPayload(request, Guid.NewGuid(), false),
// Result selector
payload => new OrderConfirmation(payload.OrderId, DateTime.UtcNow))
// Add validations
.Validate(request =>
string.IsNullOrEmpty(request.CustomerId)
? Option<OrderError>.Some(new OrderError("INVALID_CUSTOMER", "Customer ID required"))
: Option<OrderError>.None())
// Add activities
.Do(ProcessPayment)
.Do(UpdateInventory)
// Add conditional activities
.DoIf(
payload => payload.Request.Amount > 1000,
ApplyHighValueDiscount)
// Add finally activities
.Finally(LogOrderProcessing)
// Build the workflow
.Build();
// Execute the workflow
var result = await workflow.Execute(new OrderRequest("CUST123", 299.99));
// Handle the result
if (result.IsRight)
{
var confirmation = result.Right;
Console.WriteLine($"Order {confirmation.OrderId} processed at {confirmation.ProcessedAt}");
}
else
{
var error = result.Left;
Console.WriteLine($"Error: {error.Code} - {error.Message}");
}
Core Concepts
Workflow
A workflow represents a sequence of operations that processes a request and produces either a success result or an error. It's created using the WorkflowBuilder
.
WorkflowBuilder
The builder provides a fluent API for constructing workflows:
var workflow = new WorkflowBuilder<TRequest, TPayload, TSuccess, TError>(
contextFactory, // Function that creates the initial payload from the request
resultSelector) // Function that creates the success result from the final payload
.Validate(...) // Add validations
.Do(...) // Add activities
.DoIf(...) // Add conditional activities
.Branch(...) // Add branching logic
.BranchWithLocalPayload(...) // Add branch with its own isolated payload type
.Finally(...) // Add finally activities
.Build(); // Build the workflow
Validations
Validations check if the request is valid before processing begins. They return an Option<TError>
:
.Validate(request =>
string.IsNullOrEmpty(request.CustomerId)
? Option<OrderError>.Some(new OrderError("INVALID_CUSTOMER", "Customer ID required"))
: Option<OrderError>.None())
Activities
Activities are the primary building blocks of workflows. They process the payload and return either a success or failure result:
private static Either<OrderError, OrderPayload> ProcessPayment(OrderPayload payload)
{
// Process payment logic
if (successful)
{
var updatedPayload = payload with { IsProcessed = true };
return Either<OrderError, OrderPayload>.FromRight(updatedPayload);
}
else
{
return Either<OrderError, OrderPayload>.FromLeft(
new OrderError("PAYMENT_FAILED", "Failed to process payment"));
}
}
Conditional Activities
Execute activities only when specific conditions are met:
.DoIf(
payload => payload.Request.Amount > 1000, // Condition
ApplyHighValueDiscount) // Activity
Branches
Create branches for more complex conditional logic:
.Branch(payload => payload.IsExpressShipping)
.Do(CalculateExpressShippingFee)
.Do(PrioritizeOrder)
.EndBranch()
.Branch(payload => !payload.IsExpressShipping)
.Do(CalculateStandardShippingFee)
.EndBranch()
Branches with Local Payload
Create isolated branches with their own local payload type that doesn't affect the main workflow payload:
.BranchWithLocalPayload(
// Condition
payload => payload.NeedsCustomization,
// Local payload factory
mainPayload => new CustomizationPayload(
AvailableOptions: new[] { "Engraving", "Gift Wrap" },
SelectedOptions: new string[0],
CustomizationCost: 0m
),
// Branch configuration
branch => branch
.Do((mainPayload, localPayload) => {
// Activity can access and modify both payloads
var selectedOption = "Engraving";
var updatedLocalPayload = localPayload with {
SelectedOptions = new[] { selectedOption },
CustomizationCost = 10.00m
};
var updatedMainPayload = mainPayload with {
FinalPrice = mainPayload.Price + updatedLocalPayload.CustomizationCost
};
return Either<OrderError, (OrderPayload, CustomizationPayload)>.FromRight(
(updatedMainPayload, updatedLocalPayload));
})
)
Finally Blocks
Activities that execute regardless of workflow success or failure:
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- MediatR (>= 12.5.0)
- Zooper.Fox (>= 1.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Zooper.Bee:
Package | Downloads |
---|---|
Zooper.Bee.MediatR
A .NET library for building robust, functional workflows and processing pipelines. |
GitHub repositories
This package is not used by any popular GitHub repositories.