Table of Contents

Class DomainEventDispatchBehavior<TMessage, TResponse>

Namespace
Trellis.Mediator
Assembly
Trellis.Mediator.dll

Pipeline behavior that dispatches domain events accumulated on the success-value aggregate after the command handler returns. Events fire after any inner TransactionalCommandBehavior commits, so handlers see committed state.

public sealed class DomainEventDispatchBehavior<TMessage, TResponse> : IPipelineBehavior<TMessage, TResponse> where TMessage : ICommand<TResponse> where TResponse : IResult

Type Parameters

TMessage

The command type. Must implement Mediator.ICommand<TResponse>.

TResponse

The command response. Must implement IResult.

Inheritance
DomainEventDispatchBehavior<TMessage, TResponse>
Implements
IPipelineBehavior<TMessage, TResponse>
Inherited Members
Extension Methods

Remarks

Constrained to Mediator.ICommand<TResponse> so that queries returning the same aggregate types do not trigger dispatch.

A successful IResult<TAggregate> response contributes an IAggregate to the dispatch batch. Nested commands whose commits are deferred transfer their batches to the enclosing command for the same unit of work. An outer DTO, Unit, or tuple response contributes no aggregate itself but still releases nested batches after its owning successful commit. Failed responses and exceptions discard batches without clearing aggregate events.

Events are dispatched sequentially from a defensive snapshot captured before the first publish. v1 expects single-wave dispatch: handlers should be side-effect-only and must not raise additional events on the same aggregate. If the aggregate's pending-event list no longer exactly matches the snapshot after dispatch, DomainEventHandlerCascadedException is thrown and AcceptChanges() is not called so the current aggregate state remains available for inspection. Dispatch runs after the transaction has committed and is therefore not cancellable: the caller's token is not observed and handlers receive None.

Constructors

DomainEventDispatchBehavior(IDomainEventPublisher, ILogger<DomainEventDispatchBehavior<TMessage, TResponse>>)

Initializes a new instance of the DomainEventDispatchBehavior<TMessage, TResponse> class.

public DomainEventDispatchBehavior(IDomainEventPublisher publisher, ILogger<DomainEventDispatchBehavior<TMessage, TResponse>> logger)

Parameters

publisher IDomainEventPublisher

The publisher used to fan out events to registered handlers.

logger ILogger<DomainEventDispatchBehavior<TMessage, TResponse>>

A logger parameter retained for constructor compatibility with the mediator behavior registrations.

Exceptions

ArgumentNullException

Thrown when publisher or logger is null.

Methods

Handle(TMessage, MessageHandlerDelegate<TMessage, TResponse>, CancellationToken)

[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "Reflection on IResult<T>.TryGetValue against the closed generic response type. The consumer's Result<TAggregate> remains reachable through the static command handler signature, so trimming preserves it; consumers needing strict NativeAOT guarantees can supply a custom IPipelineBehavior implementation.")]
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling", Justification = "Reflection on IResult<T>.TryGetValue against the closed generic response type. The consumer's Result<TAggregate> remains reachable through the static command handler signature, so trimming preserves it; consumers needing strict NativeAOT guarantees can supply a custom IPipelineBehavior implementation.")]
public ValueTask<TResponse> Handle(TMessage message, MessageHandlerDelegate<TMessage, TResponse> next, CancellationToken cancellationToken)

Parameters

message TMessage
next MessageHandlerDelegate<TMessage, TResponse>
cancellationToken CancellationToken

Returns

ValueTask<TResponse>