MinimalDomainEvents.Dispatcher 0.2.0-alpha

This is a prerelease version of MinimalDomainEvents.Dispatcher.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package MinimalDomainEvents.Dispatcher --version 0.2.0-alpha                
NuGet\Install-Package MinimalDomainEvents.Dispatcher -Version 0.2.0-alpha                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MinimalDomainEvents.Dispatcher" Version="0.2.0-alpha" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MinimalDomainEvents.Dispatcher --version 0.2.0-alpha                
#r "nuget: MinimalDomainEvents.Dispatcher, 0.2.0-alpha"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MinimalDomainEvents.Dispatcher as a Cake Addin
#addin nuget:?package=MinimalDomainEvents.Dispatcher&version=0.2.0-alpha&prerelease

// Install MinimalDomainEvents.Dispatcher as a Cake Tool
#tool nuget:?package=MinimalDomainEvents.Dispatcher&version=0.2.0-alpha&prerelease                

MinimalDomainEvents

Minimal impact domain event raising and dispatching framework leveraging AsyncLocal to scope and track domain events raised from your domain model across the asynchronous execution context. This allows for the tracking of domain events raised in an entity, without the need for exposing a public collection of domain events on the entity, which needs to be (manually) tracked. Domain events are always raised in the current active scope. The current active scope is the deepest scope active where the entity resides in.

Packages

MinimalDomainEvents.Contract

Contains the IDomainEvent marker interface. Make sure your domain events implement this interface.

MinimalDomainEvents.Core

Reference this project from your Domain project. Exposes the DomainEventTracker class for raising domain events from your domain entities, and the IDomainEventScope interface for scoping the raising of domain events

Examples

Raising a domain event from inside your entity.

public class Customer : IEntity
{
    public Order PlaceOrder(string productId)
    {
        DomainEventTracker.RaiseDomainEvent(new OrderPlacedDomainEvent { ProductId = productId });
        return new Order(productId);
    }
}

Raising a domain event on a specific scope.

using (var scope = DomainEventTracker.CreateScope())
{
    scope.RaiseDomainEvent(new TestEvent());
}

Domain events raised using the static DomainEventTracker are raised on the current active scope (the deepest existing scope). Calling Peek on the DomainEventTracker yields the same result als calling Peek on the current active scope.

using (var scope = DomainEventTracker.CreateScope())
{
    DomainEventTracker.RaiseDomainEvent(new TestEvent("I was raised in the top scope."));
    using (var nestedScope = DomainEventTracker.CreateScope())
    {
        DomainEventTracker.RaiseDomainEvent(new TestEvent("I was raised in the nested scope."));

        using (var evenMoreNestedScope = DomainEventTracker.CreateScope())
        {
            DomainEventTracker.RaiseDomainEvent(new TestEvent("I was raised in the deepest scope."));
            DomainEventTracker.Peek().Should().HaveCount(1);
        }

        DomainEventTracker.RaiseDomainEvent(new TestEvent("I was also raised in the nested scope."));
        DomainEventTracker.Peek().Should().HaveCount(2);
    }

    DomainEventTracker.Peek().Should().HaveCount(1);
}

DomainEventTracker.Peek().Should().BeEmpty();

MinimalDomainEvents.Dispatcher

Holds the abstract ScopedDomainEventDispatcher class which creates a scope on construction, used for scoping the raising of domain events to the lifetime of this class.

Example
IServiceCollection services = new ServiceCollection();
services.AddScoped<IDomainEventDispatcher, ScopedDomainEventDispatcherImpl>();
var serviceProvider = services.BuildServiceProvider();
var controller = serviceProvider.GetRequiredService<Controller>();

internal sealed class Controller
{
    // Make sure this is registered as either transient or scoped, so that the scope
    // will no longer exist in the tracker when the lifetime ends.
    private readonly IDomainEventDispatcher _dispatcher;

    public async Task DoSomethingWithEntities()
    {
        var user = await GetUserById(id);
        user.DoOperationThatRaisesDomainEvents();
        user.DoOtherOperationThatAlsoRaisesDomainEvents();

        // All domain events raised inside entities that were instantiated in this scope or a nested scope
        // will register to the lifetime scope of the ScopedDomainEventDispatcherImpl and thus be dispatched
        // when DispatchAndClear is called.
        await _dispatcher.DispatchAndClear();
    }
}

internal sealed ScopedDomainEventDispatcherImpl : ScopedDomainEventDispatcher { ... }

MinimalDomainEvents.Dispatcher.MediatR

Contains the MediatorDispatcher, which dispatches the domain events using MediatR, as well as the DomainEventDispatchBehavior. The behavior uses the lifetime of the MediatorDispatcher to capture raised domain events during its lifetime and dispatches them when the RequestHandlerDelegate completes successfully. Make sure your domain events implement both IDomainEvent and INotification.

Usage (Microsoft.Extensions.DependencyInjection)
using MinimalDomainEvents.Dispatcher.MediatR;

IServiceCollection services = new ServiceCollection();
services.AddMediatorDispatcher();
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.3.2-alpha 76 4/4/2024
0.3.1-alpha 94 1/15/2024
0.3.0-alpha 149 12/5/2023
0.2.0-alpha 85 12/3/2023