Handly 1.0.2

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

Handly

NuGet .NET CI

Handly is a lightweight and transparent mediator-style dispatcher for .NET. Inspired by MediatR, it aims to be faster, leaner, and open-source.

🚀 Benchmarks

Performed on a MacBook M1 Pro (.NET 9, BenchmarkDotNet, Release build)

Method Mean StdDev Ratio Allocated
MediatR.Send (no behaviors) 77.24 ns 0.65 ns baseline 288 B
Handly.Dispatch (no behaviors) 103.92 ns 1.28 ns +35% 264 B
MediatR.Send (with behaviors) 270.31 ns 4.53 ns +250% 1072 B
Handly.Dispatch (with behaviors) 635.12 ns 7.28 ns +722% 864 B

✅ Why Handly?

  • Open-source and Free — no license cost, forever.
  • Transparent and Hackable — know what runs and why.
  • Performant — especially with no behaviors.
  • No Reflection at Runtime — compiled, cached, and minimal allocations.

✨ Features

  • Lightweight Dispatcher for IRequest<TResponse>
  • Pipeline behaviors (logging, validation, metrics...)
  • Assembly scanning for handler auto-registration
  • Plug-and-play DI integration
  • Dead simple API and structure

📦 Installation

dotnet add package Handly

Or via NuGet:

https://www.nuget.org/packages/Handly


👋 Getting Started

1. Define a Request

public class Ping : IRequest<string> { }

2. Create a Handler

public class PingHandler : IRequestHandler<Ping, string>
{
    public Task<string> Handle(Ping request, CancellationToken cancellationToken)
    {
        return Task.FromResult("Pong");
    }
}

3. (Optional) Add a Behavior

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;

    public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TRequest, TResponse> next,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation($"Handling {typeof(TRequest).Name}");
        var response = await next();
        _logger.LogInformation($"Handled {typeof(TRequest).Name}");
        return response;
    }
}

4. Register with DI

builder.Services.AddHandly(cfg =>
{
    cfg.RegisterHandlerFromAssembly(Assembly.GetExecutingAssembly());
    cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
});

5. Dispatch a request

public class MyService
{
    private readonly IDispatcher _dispatcher;

    public MyService(IDispatcher dispatcher)
    {
        _dispatcher = dispatcher;
    }

    public async Task ExecuteAsync()
    {
        var request = new Ping();
        var response = await _dispatcher.Dispatch(request);
        Console.WriteLine(response); // Pong
    }
}

❤️ Contributing

Pull requests are welcome! For major changes, please open an issue first.

🔒 License

MIT. Free as in freedom.

Made with ❤️ by developer who like things fast and clean.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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
1.0.2 77 5/3/2025
1.0.1 138 4/12/2025