Skip to main content
ClaudeWave
Skill64 repo starsupdated 22d ago

dotnet-domain-events-generator

Generates Domain Events and their handlers following DDD patterns. Implements event raising in entities, MediatR notification handlers, and the Outbox pattern for reliable event processing.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/ronnythedev/dotnet-clean-architecture-skills /tmp/dotnet-domain-events-generator && cp -r /tmp/dotnet-domain-events-generator/skills/09-dotnet-domain-events-generator ~/.claude/skills/dotnet-domain-events-generator
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Domain Events Generator

## Overview

Domain Events capture something significant that happened in the domain:

- **Raised by entities** - When state changes occur
- **Handled by notification handlers** - React to events
- **Outbox pattern** - Reliable event delivery
- **Decoupled** - Publisher doesn't know subscribers

## Quick Reference

| Component | Purpose | Location |
|-----------|---------|----------|
| `IDomainEvent` | Marker interface | Domain/Abstractions |
| `{Entity}{Action}DomainEvent` | Event record | Domain/{Aggregate}/Events |
| `{Event}DomainEventHandler` | Event handler | Application/{Feature} |
| `OutboxMessage` | Persisted event | Infrastructure/Outbox |

---

## Event Structure

```
/Domain/
├── Abstractions/
│   └── IDomainEvent.cs
└── {Aggregate}/
    └── Events/
        ├── {Entity}CreatedDomainEvent.cs
        ├── {Entity}UpdatedDomainEvent.cs
        └── ...

/Application/
└── {Feature}/
    └── EventHandlers/
        ├── {Event}Handler.cs
        └── ...

/Infrastructure/
└── Outbox/
    ├── OutboxMessage.cs
    ├── OutboxMessageConfiguration.cs
    └── ProcessOutboxMessagesJob.cs
```

---

## Template: Domain Event Interface

```csharp
// src/{name}.domain/Abstractions/IDomainEvent.cs
using MediatR;

namespace {name}.domain.abstractions;

/// <summary>
/// Marker interface for domain events.
/// Domain events represent something significant that happened in the domain.
/// </summary>
public interface IDomainEvent : INotification
{
    /// <summary>
    /// Unique identifier for this event instance
    /// </summary>
    Guid Id { get; }

    /// <summary>
    /// When the event occurred
    /// </summary>
    DateTime OccurredOnUtc { get; }
}
```

---

## Template: Base Domain Event Record

```csharp
// src/{name}.domain/Abstractions/DomainEvent.cs
namespace {name}.domain.abstractions;

/// <summary>
/// Base record for domain events with common properties
/// </summary>
public abstract record DomainEvent : IDomainEvent
{
    public Guid Id { get; init; } = Guid.NewGuid();
    public DateTime OccurredOnUtc { get; init; } = DateTime.UtcNow;
}
```

---

## Template: Specific Domain Events

```csharp
// src/{name}.domain/{Aggregate}/Events/{Entity}CreatedDomainEvent.cs
using {name}.domain.abstractions;

namespace {name}.domain.{aggregate}.events;

/// <summary>
/// Raised when a new {Entity} is created
/// </summary>
public sealed record {Entity}CreatedDomainEvent(
    Guid {Entity}Id) : DomainEvent;

// src/{name}.domain/{Aggregate}/Events/{Entity}UpdatedDomainEvent.cs
/// <summary>
/// Raised when a {Entity} is updated
/// </summary>
public sealed record {Entity}UpdatedDomainEvent(
    Guid {Entity}Id,
    string PropertyName,
    string? OldValue,
    string? NewValue) : DomainEvent;

// src/{name}.domain/{Aggregate}/Events/{Entity}DeactivatedDomainEvent.cs
/// <summary>
/// Raised when a {Entity} is deactivated
/// </summary>
public sealed record {Entity}DeactivatedDomainEvent(
    Guid {Entity}Id,
    string Reason) : DomainEvent;

// src/{name}.domain/{Aggregate}/Events/{Entity}DeletedDomainEvent.cs
/// <summary>
/// Raised when a {Entity} is deleted
/// </summary>
public sealed record {Entity}DeletedDomainEvent(
    Guid {Entity}Id) : DomainEvent;
```

---

## Template: Rich Domain Events

```csharp
// src/{name}.domain/Users/Events/UserRegisteredDomainEvent.cs
using {name}.domain.abstractions;

namespace {name}.domain.users.events;

/// <summary>
/// Raised when a new user registers
/// </summary>
public sealed record UserRegisteredDomainEvent : DomainEvent
{
    public Guid UserId { get; init; }
    public string Email { get; init; } = string.Empty;
    public string Name { get; init; } = string.Empty;
    public Guid OrganizationId { get; init; }

    public UserRegisteredDomainEvent(
        Guid userId,
        string email,
        string name,
        Guid organizationId)
    {
        UserId = userId;
        Email = email;
        Name = name;
        OrganizationId = organizationId;
    }
}

// src/{name}.domain/Assessments/Events/AssessmentCompletedDomainEvent.cs
/// <summary>
/// Raised when a user completes an assessment
/// </summary>
public sealed record AssessmentCompletedDomainEvent : DomainEvent
{
    public Guid AssessmentId { get; init; }
    public Guid UserId { get; init; }
    public Guid OrganizationId { get; init; }
    public string AssessmentType { get; init; } = string.Empty;
    public decimal Score { get; init; }
    public DateTime CompletedAt { get; init; }

    public AssessmentCompletedDomainEvent(
        Guid assessmentId,
        Guid userId,
        Guid organizationId,
        string assessmentType,
        decimal score,
        DateTime completedAt)
    {
        AssessmentId = assessmentId;
        UserId = userId;
        OrganizationId = organizationId;
        AssessmentType = assessmentType;
        Score = score;
        CompletedAt = completedAt;
    }
}
```

---

## Template: Raising Events in Entity

```csharp
// src/{name}.domain/{Aggregate}/{Entity}.cs
using {name}.domain.abstractions;
using {name}.domain.{aggregate}.events;

namespace {name}.domain.{aggregate};

public sealed class {Entity} : Entity
{
    // ... properties

    private {Entity}(
        Guid id,
        string name,
        Guid organizationId,
        DateTime createdAt)
        : base(id)
    {
        Name = name;
        OrganizationId = organizationId;
        CreatedAt = createdAt;
    }

    /// <summary>
    /// Factory method - raises Created event
    /// </summary>
    public static Result<{Entity}> Create(
        string name,
        Guid organizationId,
        DateTime createdAt)
    {
        // Validation...

        var {entity} = new {Entity}(
            Guid.NewGuid(),
            name,
            organizationId,
            createdAt);

        // Raise domain event
        {entity}.RaiseDomainEvent(new {Entity}CreatedDomainEvent({entity}.Id));

        return {entity};
    }

    /// <summary>
    /// Update me
dotnet-clean-architectureSkill

Scaffolds a complete .NET solution following Clean Architecture principles with proper layer separation (API, Application, Domain, Infrastructure). Creates project structure, dependency injection setup, and cross-cutting concerns configuration.

dotnet-cqrs-command-generatorSkill

Generates CQRS Commands with Handlers, Validators, and Request DTOs following Clean Architecture patterns. Commands represent actions that modify state and return Result types for proper error handling.

dotnet-cqrs-query-generatorSkill

Generates CQRS Queries with Handlers and Response DTOs for read operations. Uses Dapper for optimized read queries, bypassing the domain model for better performance.

dotnet-domain-entity-generatorSkill

Generates Domain Entities following DDD principles with factory methods, private setters, domain events, and proper encapsulation. Supports aggregate roots, child entities, and value objects.

dotnet-repository-patternSkill

Generates Repository interfaces and implementations following the Repository pattern. Provides data access abstraction for aggregate roots with EF Core implementations.

dotnet-ef-core-configurationSkill

Generates Entity Framework Core configurations using Fluent API. Maps domain entities to database tables with proper relationships, constraints, and conventions.

dotnet-legacy-api-controllersSkill

Generates RESTful API Controllers with proper routing, versioning, authorization, and MediatR integration. Follows REST conventions and Clean Architecture patterns.

dotnet-minimal-api-endpointsSkill

Generates Minimal API endpoints following Microsoft's recommended approach. Creates fast, testable HTTP APIs with minimal code using MapGet/MapPost/MapPut/MapDelete. Preferred over controller-based APIs for new projects.