Mediator.Net alternatives and similar packages
Based on the "Misc" category.
Alternatively, view Mediator.Net alternatives based on common mentions on social networks and blogs.
-
Polly
Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. From version 6.0.1, Polly targets .NET Standard 1.1 and 2.0+. -
FluentValidation
A popular .NET validation library for building strongly-typed validation rules. -
Humanizer
Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities -
Edge.js
Run .NET and Node.js code in-process on Windows, MacOS, and Linux -
ReactJS.NET
.NET library for JSX compilation and server-side rendering of React components -
ScriptCS
Write C# apps with a text editor, nuget and the power of Roslyn! -
Hashids.net
A small .NET package to generate YouTube-like hashes from one or many numbers. Use hashids when you do not want to expose your database ids to the user. -
Coravel
Near-zero config .NET library that makes advanced application features like Task Scheduling, Caching, Queuing, Event Broadcasting, and more a breeze! -
Enums.NET
Enums.NET is a high-performance type-safe .NET enum utility library -
Scientist.NET
A .NET library for carefully refactoring critical paths. It's a port of GitHub's Ruby Scientist library -
WorkflowEngine
WorkflowEngine.NET - component that adds workflow in your application. It can be fully integrated into your application, or be in the form of a specific service (such as a web service). -
HidLibrary
This library enables you to enumerate and communicate with Hid compatible USB devices in .NET. -
Warden
Define "health checks" for your applications, resources and infrastructure. Keep your Warden on the watch. -
DeviceId
A simple library providing functionality to generate a 'device ID' that can be used to uniquely identify a computer. -
Aeron.NET
Efficient reliable UDP unicast, UDP multicast, and IPC message transport - .NET port of Aeron -
Jot
Jot is a library for persisting and applying .NET application state. -
ByteSize
ByteSize is a utility class that makes byte size representation in code easier by removing ambiguity of the value being represented. ByteSize is to bytes what System.TimeSpan is to time. -
Streams
A lightweight F#/C# library for efficient functional-style pipelines on streams of data. -
LINQPad.QueryPlanVisualizer
SQL Server and PostgreSQL query execution plan visualizer for LINQPad -
Jering.Javascript.NodeJS
Invoke Javascript in NodeJS, from C# -
Valit
Valit is dead simple validation for .NET Core. No more if-statements all around your code. Write nice and clean fluent validators instead! -
DeviceDetector.NET
The Universal Device Detection library will parse any User Agent and detect the browser, operating system, device used (desktop, tablet, mobile, tv, cars, console, etc.), brand and model. -
https://github.com/minhhungit/ConsoleTableExt
A fluent library to print out a nicely formatted table in a console application C# -
FormHelper
ASP.NET Core - Transform server-side validations to client-side without writing any javascript code. (Compatible with Fluent Validation) -
SolidSoils4Arduino
C# .NET - Arduino library supporting simultaneous serial ASCII, Firmata and I2C communication -
Validot
Validot is a performance-first, compact library for advanced model validation. Using a simple declarative fluent interface, it efficiently handles classes, structs, nested members, collections, nullables, plus any relation or combination of them. It also supports translations, custom logic extensions with tests, and DI containers. -
Shielded
A strict and mostly lock-free Software Transactional Memory (STM) for .NET -
Outcome.NET
Never write a result wrapper again! Outcome.NET is a simple, powerful helper for methods that return a value, but sometimes also need to return validation messages, warnings, or a success bit. -
RecordParser
Zero Allocation Writer/Reader Parser for .NET Core -
NaturalSort.Extension
🔀 Extension method for StringComparison that adds support for natural sorting (e.g. "abc1", "abc2", "abc10" instead of "abc1", "abc10", "abc2"). -
FlatMapper
FlatMapper is a library to import and export data from and to plain text files. -
NIdenticon
NIdenticon is a library for creating simple Identicons -
AzureCrawler
Take HTML Snapshots for your Angular, Ember, Durandal or any JavaScript applications -
SystemTextJson.JsonDiffPatch
High-performance, low-allocating JSON object diff and patch extension for System.Text.Json. Support generating patch document in RFC 6902 JSON Patch format. -
BerTlv.NET
A library for parsing BER TLV data (like EMV credit cards). -
trybot
A transient fault handling framework including such resiliency solutions as Retry, Timeout, Fallback, Rate Limit and Circuit Breaker. -
AdaskoTheBeAsT.FluentValidation.MediatR
FluentValidation behavior for MediatR
Access the most powerful time series database as a service
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of Mediator.Net or a related project?
README
Mediator.Net
A mediator project for .NET
Get Packages
You can get Mediator.Net by grabbing the latest NuGet packages.
Get Started
Install the nuget package Mediator.Net
Install-Package Mediator.Net
Simple usage
// Setup a mediator builder
var mediaBuilder = new MediatorBuilder();
var mediator = mediaBuilder.RegisterHandlers(typeof(this).Assembly).Build();
Sending a command with no response
await _mediator.SendAsync(new TestBaseCommand(Guid.NewGuid()));
Sending a command with response
var pong = await _mediator.SendAsync<Ping, Pong>(new Ping());
Sending request with response
var result = await _mediator.RequestAsync<GetGuidRequest, GetGuidResponse>(new GetGuidRequest(_guid));
Publishing an event
await _mediator.Publish(new OrderPlacedEvent);
Publishing an event as the result of a command
Inside a command handler.Handle method, a IReceiveContext expose a method of Publish
public async Task Handle(IReceiveContext<DerivedTestBaseCommand> context, CancellationToken cancellationToken)
{
// Do you work
await context.Publish(new OrderPlacedEvent());
}
Create stream of responses
Sometimes you might want to get multiple reponses by one request or command, you can do that by using the CreateStream
method
// Define a StreamHandler by implementing the IStreamRequestHandler or IStreamCommandHandler interfaces for IRequest and ICommand
public class GetMultipleGuidStreamRequestHandler : IStreamRequestHandler<GetGuidRequest, GetGuidResponse>
{
public async IAsyncEnumerable<GetGuidResponse> Handle(IReceiveContext<GetGuidRequest> context, [EnumeratorCancellation] CancellationToken cancellationToken)
{
for (var i = 0; i < 5; i++)
{
await Task.Delay(100, cancellationToken);
yield return await Task.FromResult(new GetGuidResponse(Guid.NewGuid() ){Index = i});
}
}
}
// You can now get multiple reponses back by using this
IAsyncEnumerable<GetGuiResponse> result = mediator.CreateStream<GetGuidRequest, GetGuidResponse>(new GetGuidRequest(_guid));
await foreach (var r in result)
{
Console.WriteLine(r.Id.ToString());
}
How about EventHandler? What would be the use cases of a stream of events? So it is currently not supported
How about middleware? You can use middleware as normal, keep in mind that middleware will only get invoked once for each IRequest or ICommand thought that multiple reponses might return
Handling message from handler
Once a message is sent, it will reach its handlers, you can only have one handler for ICommand and IRequest and can have multi handlers for IEvent. ReceiveContext will be delivered to the handler.
class TestBaseCommandHandler : ICommandHandler<TestBaseCommand>
{
public Task Handle(ReceiveContext<TestBaseCommand> context)
{
Console.WriteLine(context.Message.Id);
return Task.FromResult(0);
}
}
// Or in async
class AsyncTestBaseCommandHandler : ICommandHandler<TestBaseCommand>
{
public async Task Handle(ReceiveContext<TestBaseCommand> context)
{
Console.WriteLine(context.Message.Id);
await Task.FromResult(0);
}
}
Handler Registration
Handlers explicit registration
var mediator = builder.RegisterHandlers(() =>
{
var binding = new List<MessageBinding>
{
new MessageBinding(typeof(TestBaseCommand), typeof(TestBaseCommandHandler)),
new MessageBinding(typeof(DerivedTestBaseCommand), typeof(DerivedTestBaseCommandHandler))
};
return binding;
}).Build();
Scan registration
var mediaBuilder = new MediatorBuilder();
var mediator = mediaBuilder.RegisterHandlers(typeof(this).Assembly).Build();
Using pipelines
There are 5 different type of pipelines you can use
GlobalReceivePipeline
This pipeline will be triggered whenever a message is sent, published or requested before it reaches the next pipeline and handler
CommandReceivePipeline
This pipeline will be triggered just after the GlobalReceivePipeline
and before it reaches its command handler, this pipeline will only be used for ICommand
EventReceivePipeline
This pipeline will be triggered just after the GlobalReceivePipeline
and before it reaches its event handler/handlers, this pipeline will only be used for IEvent
RequestReceivePipeline
This pipeline will be triggered just after the GlobalReceivePipeline
and before it reaches its request handler, this pipeline will only be used for IRequest
PublishPipeline
This pipeline will be triggered when an IEvent
is published inside your handler, this pipeline will only be used for IEvent
and is usually being used as outgoing interceptor
Setting up middlewares
The most powerful thing for the pipelines above is you can add as many middlewares as you want. Follow the following steps to setup a middlewaree
- Add a static class for your middleware
- Add a public static extension method in that class you just added, usually follow the UseXxxx naming convention
- Add another class for your middleware's specification, note that this is the implementation of your middleware
You might need some dependencies in your middleware, there are two ways to do it
- Pass them in explicitly
- Let the IoC container to resolve it for you (if you are using IoC)
Here is a sample middleware
Middleware class
public static class SerilogMiddleware
{
public static void UseSerilog<TContext>(this IPipeConfigurator<TContext> configurator, LogEventLevel logAsLevel, ILogger logger = null)
where TContext : IContext<IMessage>
{
if (logger == null && configurator.DependencyScope == null)
{
throw new DependencyScopeNotConfiguredException($"{nameof(ILogger)} is not provided and IDependencyScope is not configured, Please ensure {nameof(ILogger)} is registered properly if you are using IoC container, otherwise please pass {nameof(ILogger)} as parameter");
}
logger = logger ?? configurator.DependencyScope.Resolve<ILogger>();
configurator.AddPipeSpecification(new SerilogMiddlewareSpecification<TContext>(logger, logAsLevel));
}
}
Specification class
class SerilogMiddlewareSpecification<TContext> : IPipeSpecification<TContext> where TContext : IContext<IMessage>
{
private readonly ILogger _logger;
private readonly Func<bool> _shouldExcute;
private readonly LogEventLevel _level;
public SerilogMiddlewareSpecification(ILogger logger, LogEventLevel level, Func<bool> shouldExcute )
{
_logger = logger;
_level = level;
_shouldExcute = shouldExcute;
}
public bool ShouldExecute(TContext context, CancellationToken cancellationToken)
{
if (_shouldExcute == null)
{
return true;
}
return _shouldExcute.Invoke();
}
public Task BeforeExecute(TContext context, CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
public Task Execute(TContext context, CancellationToken cancellationToken)
{
if (ShouldExecute(context, cancellationToken))
{
switch (_level)
{
case LogEventLevel.Error:
_logger.Error("Receive message {@Message}", context.Message);
break;
case LogEventLevel.Debug:
_logger.Debug("Receive message {@Message}", context.Message);
break;
case LogEventLevel.Fatal:
_logger.Fatal("Receive message {@Message}", context.Message);
break;
case LogEventLevel.Information:
_logger.Information("Receive message {@Message}", context.Message);
break;
case LogEventLevel.Verbose:
_logger.Verbose("Receive message {@Message}", context.Message);
break;
case LogEventLevel.Warning:
_logger.Verbose("Receive message {@Message}", context.Message);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return Task.FromResult(0);
}
public Task AfterExecute(TContext context, CancellationToken cancellationToken)
{
return Task.FromResult(0);
}
public void OnException(Exception ex, TContext context)
{
throw ex;
}
}
To hook up middlewares into pipelines
var builder = new MediatorBuilder();
_mediator = builder.RegisterHandlers(() =>
{
return new List<MessageBinding>()
{
new MessageBinding(typeof(TestBaseCommand), typeof(TestBaseCommandHandlerRaiseEvent)),
new MessageBinding(typeof(TestEvent), typeof(TestEventHandler)),
new MessageBinding(typeof(GetGuidRequest), typeof(GetGuidRequestHandler))
};
})
.ConfigureGlobalReceivePipe(x =>
{
x.UseDummySave();
})
.ConfigureCommandReceivePipe(x =>
{
x.UseConsoleLogger1();
})
.ConfigureEventReceivePipe(x =>
{
x.UseConsoleLogger2();
})
.ConfigureRequestPipe(x =>
{
x.UseConsoleLogger3();
})
.ConfigurePublishPipe(x =>
{
x.UseConsoleLogger4();
})
.Build();
ReceiveContext in Handlers
As you might already noticed, mediator will deliver ReceiveContext to the handler and it has a property Message
which is the original message sent, in some cases you might have one event being handled in multiple handlers and you might want to share something between, ReceiveContext
would is good place that to register your service or instance. For example you can make a middleware and register the service from there.
Register DummyTransaction from middleware
public class SimpleMiddlewareSpecification<TContext> : IPipeSpecification<TContext>
where TContext : IContext<IMessage>
{
public bool ShouldExecute(TContext context)
{
return true;
}
public Task BeforeExecute(TContext context)
{
return Task.FromResult(0);
}
public Task Execute(TContext context)
{
if (ShouldExecute(context))
{
context.RegisterService(new DummyTransaction());
}
return Task.FromResult(0);
}
public Task AfterExecute(TContext context)
{
return Task.FromResult(0);
}
}
Get the DummyTransaction registered in the middleware from the handler
public Task Handle(ReceiveContext<SimpleCommand> context)
{
_simpleService.DoWork();
if (context.TryGetService(out DummyTransaction transaction))
{
transaction.Commit();
}
return Task.FromResult(0);
}
Using dependency injection(IoC) frameworks
Autofac
Install the nuget package Mediator.Net.Autofac
Install-Package Mediator.Net.Autofac
An extension method RegisterMediator for ContainerBuilder from Autofac is used to register the builder
The super simple use case
var mediaBuilder = new MediatorBuilder();
mediaBuilder.RegisterHandlers(typeof(TestContainer).Assembly);
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterMediator(mediaBuilder);
_container = containerBuilder.Build();
You can also setup middlewares for each pipe before register it
var mediaBuilder = new MediatorBuilder();
mediaBuilder.RegisterHandlers(typeof(TestContainer).Assembly)
.ConfigureCommandReceivePipe(x =>
{
x.UseSimpleMiddleware();
});
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterMediator(mediaBuilder);
_container = containerBuilder.Build();
StructureMap
Install-Package Mediator.Net.StructureMap
Setup an IContainer and do your normal registration, then pass it along with the MediatorBuilder to the StructureMapExtensions class to register Mediator.Net
var mediaBuilder = new MediatorBuilder();
mediaBuilder.RegisterHandlers(TestUtilAssembly.Assembly)
.ConfigureCommandReceivePipe(x =>
{
x.UseSimpleMiddleware();
});
_container = new Container();
_container.Configure(x =>
{
// Do your thing
});
StructureMapExtensions.Configure(mediaBuilder, _container);
Unity
Install-Package Mediator.Net.Unity
Setup an IUnityContainer and do your normal registration, then pass it along with the MediatorBuilder to the UnityExtensions class to register Mediator.Net
var mediaBuilder = new MediatorBuilder();
var mediaBuilder = new MediatorBuilder();
mediaBuilder.RegisterHandlers(TestUtilAssembly.Assembly)
.ConfigureCommandReceivePipe(x =>
{
x.UseSimpleMiddleware();
});
_container = new UnityContainer();
_container.RegisterType<SimpleService>();
_container.RegisterType<AnotherSimpleService>();
UnityExtensioins.Configure(mediaBuilder, _container);
SimpleInjector
Install-Package Mediator.Net.SimpleInjector
We have created a helper class InjectHelper to register all necessary components for Mediator.Net
var mediaBuilder = new MediatorBuilder();
mediaBuilder.RegisterHandlers(TestUtilAssembly.Assembly)
.ConfigureCommandReceivePipe(x =>
{
x.UseSimpleMiddleware();
});
_container = new Container();
_container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();
_container.Register<SimpleService>();
_container.Register<AnotherSimpleService>();
InjectHelper.RegisterMediator(_container, mediaBuilder);
Thought that you can have transient registration for IMediator, but we recommend to use lifetime scope, you can do constructor injection as well as the following
using (var scope = _container.BeginLifetimeScope())
{
_mediator = scope.GetInstance<IMediator>();
_task = _mediator.RequestAsync<SimpleRequest, SimpleResponse>(new SimpleRequest());
}
Middlewares
One of the key feature for Mediator.Net is you can plug as many middlewares as you like, we have implemented some common one as below
Mediator.Net.Middlewares.UnitOfWork
Install-Package Mediator.Net.Middlewares.UnitOfWork
This middleware provide a CommittableTransaction inside the context, handlers can enlist the transaction if it requires UnitOfWork Mediator.Net.Middlewares.UnitOfWork - Middleware for Mediator.Net to support unit of work.
Mediator.Net.Middlewares.Serilog
Install-Package Mediator.Net.Middlewares.Serilog
This middleware logs every message by using Serilog
Mediator.Net.Middlewares.EventStore
Install-Package Mediator.Net.Middlewares.EventStore
Middleware for Mediator.Net to write event to GetEventStore, it is a Middleware for Mediator.Net that plugs intothe publish pipeline Mediator.Net.Middlewares.UnitOfWork - Middleware for Mediator.Net to persist event to EventStore.