NMediation 0.9.1
dotnet add package NMediation --version 0.9.1
NuGet\Install-Package NMediation -Version 0.9.1
<PackageReference Include="NMediation" Version="0.9.1" />
<PackageVersion Include="NMediation" Version="0.9.1" />
<PackageReference Include="NMediation" />
paket add NMediation --version 0.9.1
#r "nuget: NMediation, 0.9.1"
#:package NMediation@0.9.1
#addin nuget:?package=NMediation&version=0.9.1
#tool nuget:?package=NMediation&version=0.9.1
NMediation
Simple, easy mediation and publishing for dotnet.

Overview
NMediation gives you:
- 📚 Simple and easy API
- 💨 Fast & Performant
- 🔀 Full async and Cancellation Token support
- 💰 Free Forever
- 🌱 Easily transition from MediatR
Table of Contents
Samples
If you would like code samples for NMediation, they may be found here in the documents.
Dependencies
NMediation has a dependency on the Microsoft.Extensions.DependencyInjection.Abstractions package to allow integration into the base container.
Installation
The easiest way to get started is to: Install with NuGet.
Install where you need with:
Install-Package NMediation
If you want to install just the base interfaces without the single dependency in certain projects.
Install-Package NMediation.Abstractions
Contents
NMediation is the simplest implementation of the Mediator and Observer patterns for the dotnet framework. The library comes with zero excessive features to weigh down performance or burden the end-user with unnecessary options.
The entire library consists of a series of interfaces alongside one base class and one type. It is purposely designed to allow a junior developer to learn in 15 minutes.
Quick Start
Setup
NMediation has a single line setup to hook itself into the base DI container.
services.AddNMedation(Assembly.GetExecutingAssembly());
...or if you have multiple projects to register, use the params argument.
services.AddNMedation(Assembly.GetExecutingAssembly(), Assembly.Load("OtherAssembly"));
Mediation
Mediation involves sending a request object to a single handler and returning a single response or a substitute for void.
It is recommended you always return an indicator to flag either the handler operation was a success or not.
Create a response object for your operation:
public class WeatherResponse
{
public IEnumerable<string> Weather { get; init; } = Enumerable.Empty<string>();
}
Create a request object that inherits the "IPayload" of type T where T is your response type.
public class WeatherRequest : IPayload<WeatherResponse>
{
}
As always, you may pass whatever metadata is required as a property.
Create a handler for the request object:
The handler will inherit from the "IPayloadHandler" interface of type T and K, where T is your request type and K is your response type.
public class WeatherHandler : IPayloadHandler<WeatherRequest, WeatherResponse>
{
private readonly IWeatherSource _weatherSource;
// Constructor omitted.
public async Task<WeatherResponse> Handle(WeatherRequest payload, CancellationToken cancellationToken)
{
var currentWeather = await _weatherSource.GetCurrentWeather();
return new WeatherResponse
{
Weather = currentWeather,
};
}
}
You may inject whatever dependencies are required for your handlers.
To start a mediation request, inject the "IMediation" interface into the source and send the request via the "Mediate" function.
// API Controller
public async Task<IActionResult> GetWeather()
{
var result = await _medation.Mediate(new WeatherRequest());
return Ok(result);
}
Publishing
Publishing involves sending an event to N number of handlers in a fire-and-forgot method with no return.
Create an event or occurrence to publish.
public class MyOccurrence : IOccurrence
{
}
The interface is to designate the type to determine which handlers to send the event to. You may add as much metadata as you require.
Create as many handlers as required to operate on the event.
Simply implement the "IOccurrenceHandler" of type T where T is the name of your event.
public class MyOccurrenceHandler : IOccurrenceHandler<MyOccurrence>
{
public Task Handle(MyOccurrence occurrence, CancellationToken cancellationToken)
{
// Do whatever is required.
}
}
To publish an event, call the "Publish" method on the "IMediation" interface.
var occurrence = new MyOccurrence();
await _medation.Publish(occurrence);
Detailed Usage
Pre- and post-processing handlers
NMediation comes with a built-in base handler that allows you to perform certain tasks before and after a handler's main task.
Let's say we want to log our payload and response object from certain handlers. That is a simple task to perform.
Have your logging handler inherit from the "BaseProcessingHandler" pass the type of your payload and response types like you would any other handler.
public abstract class BaseLoggingHandler : BaseProcessingHandler<WeatherRequest, WeatherResponse>
{
private readonly ILogger<BaseLoggingHandler> _logger;
public BaseLoggingHandler(ILogger<BaseLoggingHandler> logger)
{
_logger = logger;
}
protected override Task<WeatherRequest> PreProcessing(WeatherRequest payload, CancellationToken cancellationToken)
{
_logger.LogInformation("State of initial payload: {Payload}", payload);
return Task.FromResult(payload);
}
protected abstract Task<WeatherResponse> DoWork(WeatherRequest payload, CancellationToken cancellationToken);
protected override Task<WeatherResponse> PostProcessing(WeatherResponse response, CancellationToken cancellationToken)
{
_logger.LogInformation("State of final response: {Response}", response);
return Task.FromResult(response);
}
}
Your handler will implement your base handler and only implement the "DoWork" function.
public class MyWeatherHandler : BaseLoggingHandler
{
public MyWeatherHandler(ILogger<BaseLoggingHandler> logger)
: base(logger)
{
}
protected override Task<string> DoWork(GetWeatherRequest payload, CancellationToken cancellationToken)
{
const string response = "The weather is hot!";
return Task.FromResult(response);
}
}
You may also continue to chain the generics down to the base handler to use in any situation.
public abstract class BaseGenericHandler<TRequest, TResponse> : BaseProcessingHandler<TRequest, TResponse>
where TRequest : IPayload<TResponse>
{
protected override Task<TResponse> PostProcessing(TResponse response, CancellationToken cancellationToken)
{
return Task.FromResult(response);
}
protected override Task<TRequest> PreProcessing(TRequest payload, CancellationToken cancellationToken)
{
return Task.FromResult(payload);
}
}
Specific Pre- and Post-Processing handlers
There are also two extra base handlers will perform only pre- or post-processing operations.
public abstract class MyPreProcessingHandler : BasePreProcessingHandler<TRequest, TResponse>
{
protected override Task<TRequest> PreProcessing(TRequest payload, CancellationToken cancellationToken)
{
// Implement method and return payload.
}
}
public abstract class MyPostProcessingHandler : BasePostProcessingHandler<TRequest, TResponse>
{
protected override Task<TResponse> PostProcessing(TResponse response, CancellationToken cancellationToken)
{
// Implment method and return response.
}
}
Cancellation Token Support
You may pass a Cancellation token if you desire to either Mediation function, which will chain down to any handler.
var response = await _medation.Mediate(request, cancellationToken);
await _medation.Publish(occurrence, cancellationToken);
FAQ
Do I need NMediation?
You don't need any library. However, NMediation can be used in 99% of traditional applications. It does a great job at creating clear lines of separation between application level code and other parts of your project.
The other wonder side effect of NMediation is you can use feature folders for better project composition.
Does NMediation need a commercial license to use?
No! NMediation is 100% free forever. It uses the open source MIT license.
What are the main difference between NMediation and MediatR?
- NMediation has simpler setup.
- NMediation is blazing fast, with no excess ceremony.
- NMediation only allows for fully typed contracts, no blank objects.
- NMediation is free.
- NMediation is easier to debug pre- and post-processing because it uses base classes for those operations.
Is it hard to transition over to NMediation?
Not at all, it is best to transition over time. You can convert one handler at a time until your application is fully converted.
| 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 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 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. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
- NMediation.Abstractions (>= 0.9.1)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
- NMediation.Abstractions (>= 0.9.1)
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.3)
- NMediation.Abstractions (>= 0.9.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.