Skip to main content
ClaudeWave
Skill64 estrellas del repoactualizado 22d ago

dotnet-domain-entity-generator

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

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/ronnythedev/dotnet-clean-architecture-skills /tmp/dotnet-domain-entity-generator && cp -r /tmp/dotnet-domain-entity-generator/skills/04-dotnet-domain-entity-generator ~/.claude/skills/dotnet-domain-entity-generator
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Domain Entity Generator

## Overview

This skill generates Domain Entities following Domain-Driven Design (DDD) principles:

- **Encapsulation** - Private setters, controlled modification
- **Factory Methods** - Static `Create()` methods with validation
- **Domain Events** - State changes raise events
- **Rich Domain Model** - Behavior lives in the entity, not services
- **Invariant Protection** - Entity always in valid state

## Quick Reference

| Concept | Purpose | Example |
|---------|---------|---------|
| Aggregate Root | Entry point for aggregate | `Organization`, `User` |
| Child Entity | Part of aggregate, no own identity outside | `OrderItem`, `AssessmentDetail` |
| Value Object | Immutable, no identity | `Email`, `Money`, `Address` |
| Domain Event | Signal state change | `UserCreatedDomainEvent` |

---

## Entity Structure

```
/Domain/{Aggregate}/
├── {Entity}.cs                    # Main entity
├── {Entity}Errors.cs              # Typed errors
├── I{Entity}Repository.cs         # Repository interface
├── ValueObjects/
│   ├── {ValueObject}.cs
│   └── ...
└── Events/
    ├── {Entity}CreatedDomainEvent.cs
    ├── {Entity}UpdatedDomainEvent.cs
    └── ...
```

---

## Template: Aggregate Root 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
{
    // ═══════════════════════════════════════════════════════════════
    // PRIVATE COLLECTIONS (encapsulated)
    // ═══════════════════════════════════════════════════════════════
    private readonly List<{ChildEntity}> _{childEntities} = new();

    // ═══════════════════════════════════════════════════════════════
    // PROPERTIES (private setters)
    // ═══════════════════════════════════════════════════════════════
    public string Name { get; private set; }
    public string? Description { get; private set; }
    public bool IsActive { get; private set; }
    public DateTime CreatedAt { get; private set; }
    public DateTime UpdatedAt { get; private set; }
    
    // Navigation property (read-only collection)
    public IReadOnlyCollection<{ChildEntity}> {ChildEntities} => _{childEntities}.AsReadOnly();

    // ═══════════════════════════════════════════════════════════════
    // CONSTRUCTORS
    // ═══════════════════════════════════════════════════════════════
    
    // Private constructor for EF Core
    private {Entity}() { }

    // Private constructor for factory method
    private {Entity}(
        Guid id,
        string name,
        string? description,
        DateTime createdAt)
        : base(id)
    {
        Name = name;
        Description = description;
        IsActive = true;
        CreatedAt = createdAt;
        UpdatedAt = createdAt;
    }

    // ═══════════════════════════════════════════════════════════════
    // FACTORY METHODS
    // ═══════════════════════════════════════════════════════════════
    
    /// <summary>
    /// Creates a new {Entity} with validation
    /// </summary>
    public static Result<{Entity}> Create(
        string name,
        string? description,
        DateTime createdAt)
    {
        // Validate invariants
        if (string.IsNullOrWhiteSpace(name))
        {
            return Result.Failure<{Entity}>({Entity}Errors.NameIsRequired);
        }

        if (name.Length > 100)
        {
            return Result.Failure<{Entity}>({Entity}Errors.NameTooLong);
        }

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

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

        return {entity};
    }

    // ═══════════════════════════════════════════════════════════════
    // DOMAIN METHODS
    // ═══════════════════════════════════════════════════════════════
    
    /// <summary>
    /// Updates the {Entity} properties
    /// </summary>
    public Result Update(
        string name,
        string? description,
        DateTime updatedAt)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return Result.Failure({Entity}Errors.NameIsRequired);
        }

        if (name.Length > 100)
        {
            return Result.Failure({Entity}Errors.NameTooLong);
        }

        Name = name;
        Description = description;
        UpdatedAt = updatedAt;

        RaiseDomainEvent(new {Entity}UpdatedDomainEvent(Id));

        return Result.Success();
    }

    /// <summary>
    /// Deactivates the {Entity}
    /// </summary>
    public Result Deactivate(DateTime updatedAt)
    {
        if (!IsActive)
        {
            return Result.Failure({Entity}Errors.AlreadyDeactivated);
        }

        IsActive = false;
        UpdatedAt = updatedAt;

        RaiseDomainEvent(new {Entity}DeactivatedDomainEvent(Id));

        return Result.Success();
    }

    /// <summary>
    /// Reactivates the {Entity}
    /// </summary>
    public Result Activate(DateTime updatedAt)
    {
        if (IsActive)
        {
            return Result.Failure({Entity}Errors.AlreadyActive);
        }

        IsActive = true;
        UpdatedAt = updatedAt;

        return Result.Success();
    }

    // ═══════════════════════════════════════════════════════════════
    // CHILD ENTITY MANAGEMENT
    // ═══════════════════════════════════════════════════════════════
    
    /// <summary>
    /// Adds a child entity to this aggregate
    /// </summary>
    public Result Add{ChildEntity}({ChildEntity} {childEntity})
    {
        if ({childEntity} is null)
        {
            return Result.Failure({Entity}Errors.Child{ChildEntity}Required);
        }

        if (_{childEntities}.Any(c => c.Name == {childEntity}.Name))
        {
            return Result.Failure({Entity}Errors.Duplicate{ChildEntity}Name);
        }

        _{childEntities}.Add({childEntity
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-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.

dotnet-result-patternSkill

Implements the Result pattern for explicit error handling without exceptions. Provides Result, Result<T>, and Error types for clean, predictable control flow in domain-driven applications.