Xpandables.Results.Tasks 10.0.2

dotnet add package Xpandables.Results.Tasks --version 10.0.2
                    
NuGet\Install-Package Xpandables.Results.Tasks -Version 10.0.2
                    
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="Xpandables.Results.Tasks" Version="10.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Xpandables.Results.Tasks" Version="10.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Xpandables.Results.Tasks" />
                    
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 Xpandables.Results.Tasks --version 10.0.2
                    
#r "nuget: Xpandables.Results.Tasks, 10.0.2"
                    
#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 Xpandables.Results.Tasks@10.0.2
                    
#: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=Xpandables.Results.Tasks&version=10.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Xpandables.Results.Tasks&version=10.0.2
                    
Install as a Cake Tool

System.Results.Tasks

NuGet NuGet Downloads .NET License

Mediator implementation with pre-built pipeline request handler for CQRS dispatch.

📖 Overview

System.Results.Tasks (NuGet: Xpandables.Results.Tasks) provides IMediator / Mediator for dispatching requests through a decorator pipeline, and PipelineRequestHandler<TRequest> which builds the pipeline chain at construction time for maximum performance. Namespace: System.Results.Tasks.

Built for .NET 10 and C# 14.

✨ Features

Type File Description
IMediator IMediator.cs Contract — SendAsync<TRequest> and SendAsync<TRequest, TResponse>
Mediator Mediator.cs Sealed implementation — resolves IPipelineRequestHandler<TRequest> from DI
PipelineRequestHandler<TRequest> PipelineRequestHandler.cs Sealed — pre-builds decorator chain at construction; fast path when no decorators

⚙️ Dependency Injection

C# 14 extension members on IServiceCollection:

// Basic mediator + pipeline handler
services.AddXMediator();

// Mediator + standard pipeline decorators (pre, post, validation, exception)
services.AddXMediatorWithPipelines();

// Mediator + event sourcing pipeline decorators
services.AddXMediatorWithEventSourcingPipelines();

// Custom mediator implementation
services.AddXMediator<MyCustomMediator>();

Standard pipeline:

  1. PipelinePreHandlerDecorator
  2. PipelinePostHandlerDecorator
  3. PipelineRequireUnitOfWorkDecorator
  4. PipelineValidationDecorator
  5. PipelineExceptionDecorator

Event sourcing pipeline:

  1. PipelinePublishDomainEventDecorator
  2. PipelineEnqueueIntegrationEventDecorator
  3. PipelinePreHandlerDecorator
  4. PipelinePostHandlerDecorator
  5. PipelineRequireDataUnitOfWorkDecorator
  6. PipelineCommitDomainEventDecorator
  7. PipelineValidationDecorator
  8. PipelineExceptionDecorator

📦 Installation

dotnet add package Xpandables.Results.Tasks

Project References: Xpandables.Results.Pipelines (which transitively includes Results, Validation, Events, Data, Entities)

🚀 Quick Start

1. Register Services at Startup

using System.Results.Tasks;

var builder = WebApplication.CreateBuilder(args);

// Scan and register all sealed request handlers from the assembly
builder.Services.AddXRequestHandlers(typeof(Program).Assembly);

// Option A: Mediator with standard pipeline (pre, post, validation, exception)
builder.Services.AddXMediatorWithPipelines();

// Option B: Mediator with event sourcing pipeline
// builder.Services.AddXMediatorWithEventSourcingPipelines();

// Option C: Bare mediator (no decorators — you add them yourself)
// builder.Services.AddXMediator();

2. Define Requests and Handlers

// Query request — returns a single DTO
public sealed record GetProductByIdRequest(Guid ProductId) : IRequest<ProductDto>;

public sealed class GetProductByIdHandler(AppDbContext db)
    : IRequestHandler<GetProductByIdRequest, ProductDto>
{
    public async Task<Result<ProductDto>> HandleAsync(
        GetProductByIdRequest request, CancellationToken ct)
    {
        Product? product = await db.Products.FindAsync([request.ProductId], ct);

        if (product is null)
            return Result.NotFound<ProductDto>(
                "ProductId", $"Product {request.ProductId} not found");

        return Result.Success(new ProductDto(
            product.Id, product.Name, product.Price));
    }
}

// Command request — returns void-like Result
public sealed record DeactivateProductRequest(Guid ProductId) : IRequest;

public sealed class DeactivateProductHandler(AppDbContext db)
    : IRequestHandler<DeactivateProductRequest>
{
    public async Task<Result> HandleAsync(
        DeactivateProductRequest request, CancellationToken ct)
    {
        Product? product = await db.Products.FindAsync([request.ProductId], ct);

        if (product is null)
            return Result.NotFound("ProductId", "Product not found");

        product.IsActive = false;
        await db.SaveChangesAsync(ct);

        return Result.NoContent();
    }
}

3. Send Requests via IMediator

// Inject IMediator and dispatch requests
public sealed class ProductService(IMediator mediator)
{
    // Send a query — get a typed response
    public async Task<Result<ProductDto>> GetProductAsync(
        Guid productId, CancellationToken ct)
    {
        var request = new GetProductByIdRequest(productId);
        return await mediator.SendAsync<GetProductByIdRequest, ProductDto>(request, ct);
    }

    // Send a command — get a non-generic Result
    public async Task<Result> DeactivateProductAsync(
        Guid productId, CancellationToken ct)
    {
        var request = new DeactivateProductRequest(productId);
        return await mediator.SendAsync(request, ct);
    }
}

4. Use in a Minimal API Endpoint

app.MapGet("/api/products/{id:guid}", async (
    Guid id, IMediator mediator, CancellationToken ct) =>
{
    Result<ProductDto> result = await mediator
        .SendAsync<GetProductByIdRequest, ProductDto>(
            new GetProductByIdRequest(id), ct);

    return result.IsSuccess
        ? Results.Ok(result.Value)
        : Results.Problem(
            title: result.Title,
            detail: result.Detail,
            statusCode: (int)result.StatusCode);
});

app.MapDelete("/api/products/{id:guid}", async (
    Guid id, IMediator mediator, CancellationToken ct) =>
{
    Result result = await mediator
        .SendAsync(new DeactivateProductRequest(id), ct);

    return result.IsSuccess
        ? Results.NoContent()
        : Results.Problem(statusCode: (int)result.StatusCode);
});

5. Full Registration with Event Sourcing

// For event-sourced applications
builder.Services.AddXRequestHandlers(typeof(Program).Assembly);
builder.Services.AddXMediatorWithEventSourcingPipelines();
// This registers in order:
//   1. PipelinePublishDomainEventDecorator
//   2. PipelineEnqueueIntegrationEventDecorator
//   3. PipelinePreHandlerDecorator
//   4. PipelinePostHandlerDecorator
//   5. PipelineRequireDataUnitOfWorkDecorator
//   6. PipelineCommitDomainEventDecorator
//   7. PipelineValidationDecorator
//   8. PipelineExceptionDecorator

How the Pipeline Works

Request arrives at IMediator.SendAsync()
  │
  ▼
PipelineRequestHandler<TRequest> (pre-built delegate chain)
  │
  ├── PipelineExceptionDecorator       ← catches exceptions
  │     ├── PipelineValidationDecorator ← runs ICompositeValidator
  │     │     ├── PipelinePreHandlerDecorator  ← IRequestPreHandler
  │     │     │     ├── YOUR HANDLER           ← IRequestHandler<TRequest>
  │     │     │     └── PipelinePostHandlerDecorator ← IRequestPostHandler
  │     │     └──
  │     └──
  └── Result returned to caller

📄 License

Apache License 2.0 — Copyright © Kamersoft 2025

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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
10.0.2 138 3/15/2026
10.0.1 126 2/20/2026
10.0.0 138 1/9/2026