MyServiceBusDocs

Guide · Mediator

Use mediator dispatch inside one process.

The mediator runs commands, queries, notifications, consumers, and pipeline filters locally without a broker. It can replace MediatR in suitable applications, while broker-backed delivery remains a separate operational boundary.

Local by design

The mediator is an execution boundary for one application process. It is useful for modular monoliths, application commands and queries, lightweight tools, and interactions that may later move behind a broker boundary.

C# also provides optional mediator-only IRequest, IRequest<TResponse>, and INotification intent markers. Java uses Command, Request<TResponse>, and Notification. They do not change broker, topology, serialization, or consumer behavior, and unmarked contracts remain supported by the explicit mediator APIs.

Configure and dispatch

Use the mediator-oriented handler interfaces—IHandler<T> or Handler<T> in C#, and Handler<T> or HandlerBase<T> in Java—then select the mediator transport and dispatch through the platform's local API. Handler dependency-injection scopes, filters, retry configuration, consume contexts, and asynchronous completion still apply.

C#
Loading code…

The hosted C# bus is started by the application host. Java's standalone MediatorBus is ready after construction. In both clients, dispatch completes only after the matched handler pipelines settle, and terminal failures are returned to the caller.

Handlers can return results

Use C# IHandler<TMessage, TResult> / Handler<TMessage, TResult>, Java HandlerWithResult<TMessage, TResult>, or Kotlin Handler<TMessage, TResult> for mediator requests. The returned value is sent through the correlated response pipeline.

One runtime, three consumer shapes

Handlers are mediator-oriented consumer APIs, not a separate execution subsystem. A Handler can run behind a broker transport; an ordinary Consumer can satisfy mediator Send or Publish; and reflected or generated consumer methods participate in both modes, including response-returning methods. Choose the shape that communicates the application's intent most clearly.

01

Handler

Clear intent for local application commands and queries, while remaining broker-capable.

02

Consumer

Natural when the contract is already modeled as bus messaging, while remaining mediator-capable.

03

Consumer method

A compact reflected or generated declaration using the same topology and pipeline.

AddHandler is a mediator-friendly registration alias, not a semantic fence. AddConsumer remains valid for handler types, and handler registration remains valid with broker-backed transports.

Depend on the smaller contract

Application components can depend on C# IMediator or Java Mediator. Those interfaces expose local Send and Publish intent without destination-aware bus operations. Keep IMessageBus or the concrete Java MediatorBus at infrastructure boundaries that genuinely need the wider contract.

Mediator semantics

These semantics preserve familiar command, query, and notification intent without claiming MediatR source compatibility or coupling broker-backed bus contracts to mediator request markers.

Publish(message) is the close match to MediatR notification publication: dispatch is selected by message type, every compatible local handler runs, and the operation completes after all handler pipelines settle. Publishing with no compatible handler completes successfully.

Send means exactly one local handler

Mediator Send(message) is selected by message type and fails immediately when no compatible handler—or more than one—is registered. This matches the command and query cardinality people expect from a mediator while keeping publish fan-out explicit.

A request contract carries its response type, giving C# the inferred call expected from mediator semantics. Java provides the equivalent typed future and exposes responseType() because the JVM erases generic response types at runtime. Explicit two-type/class-token overloads remain available for existing contracts, and C# also exposes a request client for teams that prefer the MassTransit-familiar shape.

C#
Loading code…

Directed delivery remains a bus-shaped operation. Use a C# send endpoint or Java sendTo(destination, message) when the destination itself is part of the contract or you want to preserve a future broker boundary.

Generate the dispatch boundary

MyServiceBus provides a C# source generator and a Java JSR 269 annotation processor. They emit explicit typed handler and consumer registrations with direct-call adapters, avoiding reflection-based discovery and method invocation on the generated path. That makes the mediator useful in trimmed and AOT-oriented applications as well as ordinary managed runtimes.

C#
Loading code…
Generation is an opt-in optimization, not a blanket “zero reflection” claim

Generated catalogs remove the consumer registration and dispatch reflection boundaries. Serialization, dependency injection, proxies, and extensions may still introduce reflection unless the application configures their corresponding generated or explicit paths.

Choose the local message intent

01

Commands

Send a one-way command to exactly one type-routed local handler.

02

Queries

Send to one result handler and await its asynchronous response.

03

Notifications

Publish a local fact when multiple consumers inside the process may react.

04

Behaviors

Apply validation, logging, telemetry, and opt-in retry through consumer filters.

Use the filters and middleware guide to map validation, logging, authorization, transactions, and retry onto the shared handler pipeline.

Behavior and migration differences from MediatR

MyServiceBus supports notification fan-out, type-routed single-handler send, cardinality validation, and result-bearing requests. It is not source-compatible with MediatR: contracts, handler interfaces, registration, pipeline filters, and result access must be migrated deliberately. Generated handler registration and direct invocation are available in C# and Java, and the same consumer types can also run behind a broker transport.

MediatR remains the established dedicated .NET mediator with a broader mediator-specific ecosystem. MyServiceBus is MIT-licensed; MediatR 13 and later use a dual commercial/reciprocal license and require a license key. Review the current MediatR license ↗ for the exact terms and community eligibility.

Relationship to MassTransit mediator

MassTransit also provides mediator-style in-process dispatch as part of its distributed application framework ↗. MyServiceBus mediator-only applications do not require a broker, but compatibility with MassTransit's distributed wire profile does not imply source compatibility with its mediator APIs.

Why use a mediator instead of a method call?

A method call is simplest when the caller should know the callee directly. A mediator helps when the application benefits from message intent, handler discovery, per-dispatch scopes, fan-out, or a consistent behavior pipeline.

METHOD CALL

Direct collaboration

The caller selects a dependency and invokes a known operation.

Best for:

Simple, explicit application code with no dispatch behavior.

MEDIATOR

Local message dispatch

The caller expresses intent and registered consumers run through a shared pipeline.

Best for:

Local boundaries that benefit from decoupling, scopes, fan-out, or behaviors.

Know where the process boundary ends

The mediator does not provide broker durability, independent delivery, competing consumers, acknowledgements, or redelivery after a process exit. Delayed retries and scheduled work that exist only in memory disappear with the process.

Externally observable facts belong on the broker

If another process may need an event, publish it through the broker-backed bus. Do not treat mediator and broker publication as interchangeable paths: their delivery, retry, observability, and failure semantics differ.

NextMove from local dispatch to durable messaging
Reliability and faults →