Class DomainEventDispatchBehavior<TMessage, TResponse>
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
TMessageThe command type. Must implement Mediator.ICommand<TResponse>.
TResponseThe 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
publisherIDomainEventPublisherThe publisher used to fan out events to registered handlers.
loggerILogger<DomainEventDispatchBehavior<TMessage, TResponse>>A logger parameter retained for constructor compatibility with the mediator behavior registrations.
Exceptions
- ArgumentNullException
Thrown when
publisherorloggeris 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
messageTMessagenextMessageHandlerDelegate<TMessage, TResponse>cancellationTokenCancellationToken
Returns
- ValueTask<TResponse>