Convert Figma logo to code with AI

jbogard logoMediatR

Simple, unambitious mediator implementation in .NET

11,001
1,164
11,001
18

Top Related Projects

2,710

Cecil is a library to inspect, modify and create .NET programs and libraries.

This repository contains a suite of libraries that provide facilities commonly needed when creating production-ready applications.

3,570

Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection

Quick Overview

MediatR is a simple, unambitious mediator implementation in .NET. It supports request/response, commands, queries, notifications, and events, using a mediator pattern to reduce dependencies between objects. MediatR helps to decouple the in-process sending of messages from handling messages.

Pros

  • Simplifies application architecture by reducing direct dependencies between components
  • Supports various types of messages: requests, commands, queries, and notifications
  • Easy to integrate with dependency injection containers
  • Lightweight and has minimal impact on performance

Cons

  • Can lead to overuse, potentially complicating simple scenarios
  • May introduce additional indirection, making code flow harder to follow
  • Requires careful design to avoid creating a "god object" mediator
  • Learning curve for developers unfamiliar with the mediator pattern

Code Examples

  1. Defining a request and handler:
public class PingRequest : IRequest<string> { }

public class PingHandler : IRequestHandler<PingRequest, string>
{
    public Task<string> Handle(PingRequest request, CancellationToken cancellationToken)
    {
        return Task.FromResult("Pong");
    }
}
  1. Sending a request:
public class SomeService
{
    private readonly IMediator _mediator;

    public SomeService(IMediator mediator)
    {
        _mediator = mediator;
    }

    public async Task<string> DoPing()
    {
        return await _mediator.Send(new PingRequest());
    }
}
  1. Publishing a notification:
public class ProductAddedNotification : INotification
{
    public int ProductId { get; set; }
}

public class EmailNotificationHandler : INotificationHandler<ProductAddedNotification>
{
    public Task Handle(ProductAddedNotification notification, CancellationToken cancellationToken)
    {
        // Send email logic here
        return Task.CompletedTask;
    }
}

// Publishing the notification
await _mediator.Publish(new ProductAddedNotification { ProductId = 123 });

Getting Started

  1. Install MediatR via NuGet:

    dotnet add package MediatR
    
  2. Register MediatR in your dependency injection container:

    services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly));
    
  3. Create a request and handler:

    public record MyRequest(int Id) : IRequest<string>;
    
    public class MyHandler : IRequestHandler<MyRequest, string>
    {
        public Task<string> Handle(MyRequest request, CancellationToken cancellationToken)
        {
            return Task.FromResult($"Response for Id: {request.Id}");
        }
    }
    
  4. Use MediatR in your application:

    public class MyController : ControllerBase
    {
        private readonly IMediator _mediator;
    
        public MyController(IMediator mediator)
        {
            _mediator = mediator;
        }
    
        public async Task<IActionResult> Get(int id)
        {
            var result = await _mediator.Send(new MyRequest(id));
            return Ok(result);
        }
    }
    

Competitor Comparisons

2,710

Cecil is a library to inspect, modify and create .NET programs and libraries.

Pros of Cecil

  • Specialized for .NET assembly manipulation and inspection
  • Provides low-level access to IL code and metadata
  • Widely used in tools like Mono.Linker and Unity3D

Cons of Cecil

  • Steeper learning curve due to its low-level nature
  • Less suitable for high-level application architecture patterns
  • Requires more code to achieve common tasks compared to MediatR

Code Comparison

Cecil (assembly manipulation):

var assembly = AssemblyDefinition.ReadAssembly("MyAssembly.dll");
var type = assembly.MainModule.GetType("MyNamespace.MyClass");
var method = type.Methods.First(m => m.Name == "MyMethod");
method.Body.Instructions.Clear();
assembly.Write("ModifiedAssembly.dll");

MediatR (mediator pattern implementation):

public class MyRequest : IRequest<MyResponse> { }
public class MyHandler : IRequestHandler<MyRequest, MyResponse>
{
    public Task<MyResponse> Handle(MyRequest request, CancellationToken cancellationToken)
    {
        // Handle the request and return a response
    }
}

Cecil is focused on low-level assembly manipulation, while MediatR implements the mediator pattern for decoupling application components. Cecil is more suitable for tooling and framework development, whereas MediatR is better for structuring application logic and implementing CQRS patterns.

This repository contains a suite of libraries that provide facilities commonly needed when creating production-ready applications.

Pros of Extensions

  • Broader scope, offering a wide range of utility extensions for .NET applications
  • Official Microsoft support and integration with the .NET ecosystem
  • Regular updates and maintenance aligned with .NET release cycles

Cons of Extensions

  • Less focused on specific design patterns like mediator
  • May require more setup and configuration for specific use cases
  • Potentially steeper learning curve due to its broader scope

Code Comparison

MediatR:

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

Extensions (Dependency Injection):

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>();
    services.AddScoped<IAnotherService, AnotherService>();
}

While MediatR focuses on implementing the mediator pattern for decoupling request/response handling, Extensions provides a broader set of utilities, including dependency injection, logging, and configuration. MediatR offers a more specialized solution for CQRS-like architectures, while Extensions aims to enhance the overall .NET development experience with various utility extensions.

3,570

Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection

Pros of Scrutor

  • Focuses on assembly scanning and registration of services, providing more flexibility in service registration
  • Offers advanced filtering capabilities for service registration, including attribute-based filtering
  • Supports convention-based registration, making it easier to register multiple services following a pattern

Cons of Scrutor

  • Lacks built-in mediator pattern implementation, which MediatR provides out-of-the-box
  • May require more setup and configuration compared to MediatR's simpler approach
  • Does not include request/response handling or notification features

Code Comparison

Scrutor:

services.Scan(scan => scan
    .FromAssemblyOf<ITransientService>()
    .AddClasses(classes => classes.AssignableTo<ITransientService>())
    .AsImplementedInterfaces()
    .WithTransientLifetime());

MediatR:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly));

While Scrutor provides more granular control over service registration, MediatR offers a simpler setup for implementing the mediator pattern. Scrutor excels in scenarios requiring complex service registration logic, whereas MediatR is better suited for applications focusing on request/response handling and notifications.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

MediatR

CI NuGet NuGet MyGet (dev)

Simple mediator implementation in .NET

In-process messaging with no dependencies.

Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance.

Examples in the wiki.

Installing MediatR

You should install MediatR with NuGet:

Install-Package MediatR

Or via the .NET Core command line interface:

dotnet add package MediatR

Either commands, from Package Manager Console or .NET Core CLI, will download and install MediatR and all required dependencies.

Using Contracts-Only Package

To reference only the contracts for MediatR, which includes:

  • IRequest (including generic variants)
  • INotification
  • IStreamRequest

Add a package reference to MediatR.Contracts

This package is useful in scenarios where your MediatR contracts are in a separate assembly/project from handlers. Example scenarios include:

  • API contracts
  • GRPC contracts
  • Blazor

Registering with IServiceCollection

MediatR supports Microsoft.Extensions.DependencyInjection.Abstractions directly. To register various MediatR services and handlers:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Startup>());

or with an assembly:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly));

This registers:

  • IMediator as transient
  • ISender as transient
  • IPublisher as transient
  • IRequestHandler<,> concrete implementations as transient
  • IRequestHandler<> concrete implementations as transient
  • INotificationHandler<> concrete implementations as transient
  • IStreamRequestHandler<> concrete implementations as transient
  • IRequestExceptionHandler<,,> concrete implementations as transient
  • IRequestExceptionAction<,>) concrete implementations as transient

This also registers open generic implementations for:

  • INotificationHandler<>
  • IRequestExceptionHandler<,,>
  • IRequestExceptionAction<,>

To register behaviors, stream behaviors, pre/post processors:

services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly);
    cfg.AddBehavior<PingPongBehavior>();
    cfg.AddStreamBehavior<PingPongStreamBehavior>();
    cfg.AddRequestPreProcessor<PingPreProcessor>();
    cfg.AddRequestPostProcessor<PingPongPostProcessor>();
    cfg.AddOpenBehavior(typeof(GenericBehavior<,>));
    });

With additional methods for open generics and overloads for explicit service types.