MicroKit.Events 1.0.0-preview.2

This is a prerelease version of MicroKit.Events.
dotnet add package MicroKit.Events --version 1.0.0-preview.2
                    
NuGet\Install-Package MicroKit.Events -Version 1.0.0-preview.2
                    
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="MicroKit.Events" Version="1.0.0-preview.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MicroKit.Events" Version="1.0.0-preview.2" />
                    
Directory.Packages.props
<PackageReference Include="MicroKit.Events" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MicroKit.Events --version 1.0.0-preview.2
                    
#r "nuget: MicroKit.Events, 1.0.0-preview.2"
                    
#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.
#:package MicroKit.Events@1.0.0-preview.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MicroKit.Events&version=1.0.0-preview.2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=MicroKit.Events&version=1.0.0-preview.2&prerelease
                    
Install as a Cake Tool

MicroKit.Events

Domain and integration event contracts for .NET 10. Full distributed tracing context — CorrelationId, CausationId, RequestId, IdempotencyKey, and a metadata dictionary — built into every event, with zero third-party dependencies in the contracts package.


What makes this production-grade

Richer tracing contract than most event libraries. IEvent carries six tracing fields: CorrelationId, CausationId, RequestId, IdempotencyKey, a free-form IReadOnlyDictionary<string, string>? Metadata, and both TimestampUtc (when the event object was created) and OccurredOnUtc (when the business fact occurred — settable for event sourcing replay). A naive implementation has one or none of these.

MessageType is computed, not declared. EventBase.MessageType returns GetType().FullName!. There is no string property to keep in sync with the class name. Rename the class and the routing key updates automatically everywhere.

protected init for tracing fields. Subclasses pass tracing context through the constructor using C# init-only setters, keeping the properties immutable after construction. The compiler enforces this — there is no set to call later.

Two distinct contracts by deployment boundary. IEvent (domain events, in-process) carries the full six-field tracing surface. IIntegrationEvent (cross-service events) carries only Id, OccurredOnUtc, MessageType, and CorrelationId — the minimal contract needed across a service boundary without leaking internal request context.


Installation

# Contracts — IEvent, IIntegrationEvent, IEventBase, IEventPublisher — zero deps
dotnet add package MicroKit.Events.Contracts

# EventBase, IntegrationEventBase concrete base classes
dotnet add package MicroKit.Events

Usage

Domain event (in-process)

Inherit from EventBase to get all tracing fields automatically.

using MicroKit.Events;

public sealed class OrderShippedEvent : EventBase
{
    public Guid OrderId { get; }
    public string TrackingNumber { get; }

    public OrderShippedEvent(
        Guid orderId,
        string trackingNumber,
        string? correlationId = null,
        string? causationId = null)
    {
        OrderId = orderId;
        TrackingNumber = trackingNumber;
        CorrelationId = correlationId;   // protected init — set once, immutable
        CausationId = causationId;
    }
}

EventBase members supplied automatically:

Member Value
Id Guid.NewGuid() — generated at construction
TimestampUtc DateTimeOffset.UtcNow — when the object was created
OccurredOnUtc DateTimeOffset.UtcNow — overridable via protected init for replay
MessageType GetType().FullName! — computed, never declared
CorrelationId null unless passed via protected init
CausationId null unless passed via protected init
RequestId null unless passed via protected init
IdempotencyKey null unless passed via protected init
Metadata null unless passed via protected init

Integration event (cross-service)

Use IntegrationEventBase for events published to the message broker. The contract is intentionally narrower — only what the receiving service needs.

using MicroKit.Events;

public sealed class OrderConfirmedIntegrationEvent : IntegrationEventBase
{
    public Guid OrderId { get; }
    public string CustomerId { get; }
    public decimal TotalAmount { get; }

    public OrderConfirmedIntegrationEvent(
        Guid orderId,
        string customerId,
        decimal totalAmount,
        string? correlationId = null)
    {
        OrderId = orderId;
        CustomerId = customerId;
        TotalAmount = totalAmount;
        CorrelationId = correlationId;
    }
}

IntegrationEventBase supplies: Id, OccurredOnUtc, MessageType (GetType().FullName!), and CorrelationId. There is no IdempotencyKey or RequestId — those are internal concerns.

Publishing via IEventPublisher

IEventPublisher is the in-process publishing contract. Wire an implementation (e.g. MediatR-backed) in your composition root.

using MicroKit.Events.Contracts;

public sealed class DomainEventDispatcher
{
    private readonly IEventPublisher _publisher;

    public DomainEventDispatcher(IEventPublisher publisher) => _publisher = publisher;

    // Called after the unit of work commits — domain events carry aggregates' side effects
    public Task DispatchAsync(IEnumerable<IDomainEvent> events, CancellationToken ct) =>
        _publisher.PublishRangeAsync(events.Cast<IEvent>(), ct);
}

For integration events, enqueue them into the Outbox rather than publishing directly:

// Inside a command handler — written atomically with the aggregate save
var evt = new OrderConfirmedIntegrationEvent(order.Id, order.CustomerId, order.Total, correlationId);

await _outboxService.EnqueueAsync(
    tenantId: _tenant.Tenant!.Id,
    messageId: evt.Id.ToString(),
    payload: evt,
    destination: new OutboxDestination { PublishToBroker = true, BrokerTopic = "orders.confirmed" },
    correlationId: evt.CorrelationId,
    cancellationToken: ct);

See MicroKit.Messaging for outbox setup.

Event sourcing: override OccurredOnUtc

For replay scenarios where the business timestamp must differ from the object creation time:

public sealed class OrderPlacedEvent : EventBase
{
    public Guid OrderId { get; }

    public OrderPlacedEvent(Guid orderId, DateTimeOffset occurredAt)
    {
        OrderId = orderId;
        OccurredOnUtc = occurredAt;   // protected init — set to historical timestamp
    }
}

Configuration

No DI registration is required for either package. They are pure base classes and interfaces.

Register IEventPublisher implementations in the DI container of your composition root:

// Example: MediatR-backed domain event publisher
services.AddScoped<IEventPublisher, MediatREventPublisher>();

Package dependency graph

MicroKit.Events.Contracts
    (no NuGet dependencies)

MicroKit.Events
    MicroKit.Events.Contracts
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.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
1.0.0-preview.2 57 5/12/2026
1.0.0-preview.1 49 5/12/2026