MediatR

MediatR

🌍 Language: English | Español

In-process messaging for Delphi β€” commands, queries, and notifications dispatched through a single IMediator interface. Inspired by the .NET MediatR library.

Delphi 12+ License


Concepts

Type Direction Returns Use case
IRequest 1 β†’ 1 handler β€” Command (fire-and-forget)
IRequest<TResponse> 1 β†’ 1 handler TResponse Query
INotification 1 β†’ N handlers β€” Domain event

Quick Start β€” Command

// 1. Define command
type
  TCreateOrderCommand = class(TRequest)
    OrderId: Integer;
  end;

// 2. Implement handler
type
  TCreateOrderHandler = class(TRequestHandler<TCreateOrderCommand>)
    procedure Handle(Request: TCreateOrderCommand); override;
  end;

// 3. Register handler
Services.AddTransient<IRequestHandler<TCreateOrderCommand>, TCreateOrderHandler>;

// 4. Dispatch
Mediator.Send<TCreateOrderCommand>(Cmd);

Quick Start β€” Query

type
  TGetOrderQuery    = class(TRequest<TOrderDTO>);
  TGetOrderHandler  = class(TResponseHandler<TOrderDTO, TGetOrderQuery>)
    function Handle(Request: TGetOrderQuery): TOrderDTO; override;
  end;

var DTO := Mediator.Send<TOrderDTO, TGetOrderQuery>(Query);

Quick Start β€” Notification

type
  TOrderCreatedEvent    = class(TNotification);
  TEmailNotifyHandler   = class(TNotificacionHandler<TOrderCreatedEvent>)
    procedure Handle(Notification: TOrderCreatedEvent); override;
  end;

// Register as many handlers as needed
Services.AddTransient<INotificationHandler<TOrderCreatedEvent>, TEmailNotifyHandler>;
Services.AddTransient<INotificationHandler<TOrderCreatedEvent>, TAuditLogHandler>;

// Publish β€” ALL handlers are called
Mediator.Publish<TOrderCreatedEvent>(Evt);

DI Registration

uses Daf.MediatR.DependencyInjection;

Services.AddMediatR;   // registers IMediator singleton + scans for handlers

Or manually per handler:

Services.AddTransient<IRequestHandler<TMyCommand>, TMyCommandHandler>;

Documentation

  • πŸ“– Usage Guide β€” IMediatorHelper, ARC responses, pipeline, [MediatorAbstract], DI scanning

Abstractions

MediatR.Abstractions

🌍 Language: English | Español

Core interfaces and base classes for the DAFce MediatR in-process messaging. Reference these from application code and handler implementations without taking a dependency on the concrete mediator.


Interfaces

IRequest

Fire-and-forget command β€” dispatched to exactly one handler, no return value.

IRequest = interface
end;

IRequest<TResponse>

Query β€” dispatched to exactly one handler, returns TResponse.

IRequest<TResponse> = interface(IRequest)
end;

INotification

Event β€” published to all registered handlers.

INotification = interface
end;

IMediator

IMediator = interface
  procedure Send<TRequest: IRequest>(Request: TRequest); overload;
  function  Send<TResponse; TRequest: IRequest<TResponse>>(
              Request: TRequest): TResponse; overload;
  procedure Publish<TNotification: INotification>(
              Notification: TNotification);
end;

IMediatorHelper

Extends IMediator with SendARC β€” returns the response wrapped in ARC<TResponse> for safe reference-counted ownership.

IMediatorHelper = interface(IMediator)
  function SendARC<TResponse: IInterface; TRequest: IRequest<TResponse>>(
             Request: TRequest): ARC<TResponse>;
end;

IRequestHandler<TRequest>

IRequestHandler<TRequest: IRequest> = interface
  procedure Handle(Request: TRequest);
end;

IResponseHandler<TResponse, TRequest>

IResponseHandler<TResponse; TRequest: IRequest<TResponse>> = interface
  function Handle(Request: TRequest): TResponse;
end;

INotificationHandler<TNotification>

INotificationHandler<TNotification: INotification> = interface
  procedure Handle(Notification: TNotification);
end;

Base classes

Class Use
TRequest Inherit to define a command
TRequest<TResponse> Inherit to define a query
TNotification Inherit to define an event
TRequestHandler<TReq> Inherit to handle a command β€” override Handle
TResponseHandler<TRes,TReq> Inherit to handle a query β€” override Handle
TNotificacionHandler<TNot> Inherit to handle an event β€” override Handle

Attributes

[MediatorAbstract]

Apply to abstract handler base classes to prevent the mediator from resolving them directly:

[MediatorAbstract]
TBaseHandler<T: TRequest> = class(TRequestHandler<T>);