Search Results for

      Show / Hide Table of Contents

      Intent.Application.Mediator.DomainEvents

      Dispatches the domain events raised by your entities through the source-generated Mediator library, and generates the handlers that react to them. Every handler body is written by an AI agent from the interactions you model, not by the Software Factory.

      This module is the domain-event satellite of Intent.Application.Mediator. The core module installs it automatically when Intent.DomainEvents is present in the application.

      What this module generates

      Output Generated when Purpose
      DomainEventNotification<TDomainEvent> Always Abstract base class implementing Mediator's INotification. Exposes the wrapped event as DomainEvent. Written to Common/Models in the Application layer.
      {DomainEventName}Notification One per domain event in the Domain designer Sealed wrapper deriving from DomainEventNotification<TDomainEvent>.
      DomainEventNotificationFactory Always Static class with a Create switch that maps a domain event to its wrapper.
      DomainEventService Always Implements the IDomainEventService interface from Intent.DomainEvents, and publishes the wrapped event through Mediator's IPublisher. Registered with the Infrastructure DI concern at per-service-call (scoped) lifetime.
      Explicit domain event handler One per Domain Event Handler element in the Services designer INotificationHandler<T> implementation with one Handle method per handled domain event. Each Handle is a stub.
      Default domain event handler One per domain event with no modelled handler, only when Create implicit domain event handlers is on A {DomainEventName}Handler class with a single stub Handle.
      mediator-domain-event-handler skill Always A SKILL.md teaching an AI agent how to write the handler bodies.

      No AI task is raised. An agent finds the handlers to write through the skill (see below): a handler still needs writing while its body holds the // IntentInitialGen marker and throws NotImplementedException.

      NuGet packages added to the generated application: Mediator.Abstractions 3.0.2 (locked) and Microsoft.Extensions.Logging 10.0.9.

      Settings

      Application settings, group Domain Event Settings:

      Setting Default Effect
      Create implicit domain event handlers Off When on, a default handler stub is generated for every domain event that is not handled by any modelled Domain Event Handler. When off, a domain event with no modelled handler has no handler, and publishing it is a no-op.

      The default is off because every generated handler is a stub that throws until an agent implements it. An implicit handler for an event nobody asked to handle would throw on every publish until then.

      How events are dispatched

      1. An entity raises a domain event.
      2. The infrastructure calls DomainEventService.Publish, which logs the event and calls DomainEventNotificationFactory.Create.
      3. The factory returns the sealed wrapper for the event, and DomainEventService publishes it with IPublisher.Publish.
      4. Mediator delivers the wrapper to every INotificationHandler<T> registered for it.

      The wrappers and the factory exist because Mediator's source generator cannot see an open generic type such as DomainEventNotification<T>. Each domain event gets a concrete wrapper, and the factory chooses the right one with a plain switch, without reflection.

      Things to know about the factory:

      • Every domain event has a case. A derived event is placed before its base event so the base case does not swallow it.
      • An event with no case throws InvalidOperationException rather than being dropped.

      Publishing is sequential and handler failures propagate to the caller. That behaviour comes from the Mediator configuration generated by Intent.Application.Mediator, not from this module.

      Generated shapes

      Names below are illustrative.

      The wrapper for a domain event:

      public sealed class OrderPlacedDomainEventNotification : DomainEventNotification<OrderPlacedDomainEvent>
      {
          public OrderPlacedDomainEventNotification(OrderPlacedDomainEvent domainEvent) : base(domainEvent)
          {
          }
      }
      

      An explicit handler, as first generated:

      [IntentManaged(Mode.Merge, Signature = Mode.Fully)]
      public class OrderPlacedDomainEventHandler : INotificationHandler<OrderPlacedDomainEventNotification>
      {
          [IntentManaged(Mode.Merge)]
          public OrderPlacedDomainEventHandler()
          {
          }
      
          [IntentManaged(Mode.Fully, Body = Mode.Merge)]
          public async ValueTask Handle(OrderPlacedDomainEventNotification notification, CancellationToken cancellationToken)
          {
              // IntentInitialGen
              // TODO: Implement Handle (OrderPlacedDomainEventHandler) functionality
              throw new NotImplementedException("Your implementation here...");
          }
      }
      

      A handler that handles several domain events implements INotificationHandler<T> once per event and has one Handle method per event.

      The class and signatures stay under the Software Factory's control. The constructor is merge-managed so an agent can add injected dependencies. The Handle body is the part that belongs to the agent.

      AI-written handlers

      This module never turns modelled interactions into code. It generates the stub, tells the agent what to implement, and leaves the body alone afterwards.

      The model is the specification

      Model the handler in the Services designer: a Domain Event Handler element, associated to each domain event it handles, with the interactions that should happen drawn from each handled event. Field mappings are not modelled and not read. The agent decides which event data populates which property from names and meaning.

      The skill

      mediator-domain-event-handler is generated as SKILL.md into the application's AI skills folder. It covers:

      • how the handler receives the event (notification.DomainEvent) and why the signature is never edited;
      • how to read the handler's associations from the Services designer and implement them in order, and what each interaction type means;
      • keeping the handler in step with the model: re-read the associations whenever the handler is implemented or revisited, because adding or changing an association changes no generated file;
      • eventing, saving and idempotency rules, and the layer boundaries to respect.

      Each generated handler class also carries an AI summary and context line pointing at this skill.

      Revisiting a handler after a model change

      Changing the associations of an implemented handler produces no generated change, so no task is raised. Ask the agent to revisit the handler, or have it re-read the associations as the skill instructs. Nothing in this module detects the change for you.

      A rule on the Domain Event Handler element

      This module adds an AI rule to the Domain Event Handler element in the Services designer. It tells an agent that is editing the model that the handler body is AI-written, and that creating a handler, or changing its associations, means revisiting the handler body in the same piece of work. An agent that edits the model without reading the element's rules will miss it, so the skill carries the same guidance.

      Requirements

      This module expects these modules in the application:

      • Intent.Application.Mediator, the core module. It owns the Mediator configuration and pipeline.
      • Intent.DomainEvents, which generates the domain event classes, the event base type and the IDomainEventService interface this module builds on.
      • Intent.Modelers.Domain.Events and Intent.Modelers.Services, for the Domain Event and Domain Event Handler elements.

      Interactions drawn from a handled domain event can only be modelled if the designer extensions that provide them are installed. The task text recognises these interaction types: Create, Update, Delete and Query Entity; Call Service Operation; Send Command; Publish Integration Event; Send Integration Command.

      This module does not depend on Intent.Application.DomainInteractions.

      Moving from another domain-event module

      Do not run this module alongside Intent.MediatR.DomainEvents or Intent.Application.Wolverine.DomainEvents. Each generates its own DomainEventService for the same IDomainEventService interface and its own handlers.

      When moving from Intent.MediatR.DomainEvents, the handler parameter type changes from DomainEventNotification<X> to the generated XNotification. Before swapping modules, mark each existing handler's whole Handle method [IntentManaged(Mode.Ignore)], and the handler's fields and constructor too. A body-only ignore no longer matches the new signature, so the Software Factory would replace the method with a stub. After the swap, the old method survives beside the new stub: move the body across and delete the old method. The core module's README describes the whole MediatR migration.

      Related modules

      • Intent.Application.Mediator: the core module this one extends.
      • Intent.DomainEvents: generates the domain event classes and the IDomainEventService interface.
      • Edit this page
      ☀
      ☾
      In this article
      Back to top Copyright © 2017-, Intent Architect Holdings Ltd