Skip to content

Latest commit

 

History

History
74 lines (55 loc) · 1.73 KB

File metadata and controls

74 lines (55 loc) · 1.73 KB

Vulthil.SharedKernel

Use Vulthil.SharedKernel for domain primitives reused across bounded contexts.

When to use

  • Entities, aggregate roots, and domain event abstractions
  • Shared domain exceptions and base contracts

Pattern

  • Keep business invariants inside domain types
  • Raise domain events from aggregate roots
  • Keep domain model independent from infrastructure concerns

Usage

Defining an entity

Entities compare by identity, so the identifier type must have value equality — use a record (or readonly record struct), not a plain class:

public sealed record UserId(Guid Value);

public sealed class User : AggregateRoot<UserId>
{
    public string Email { get; private set; }

    private User(UserId id, string email) : base(id)
    {
        Email = email;
    }

    public static User Create(string email)
    {
        var user = new User(new UserId(Guid.NewGuid()), email);
        user.Raise(new UserCreatedEvent(user.Id));
        return user;
    }
}

Defining a domain event

public sealed record UserCreatedEvent(UserId UserId) : IDomainEvent;

Handling a domain event

public sealed class UserCreatedEventHandler : IDomainEventHandler<UserCreatedEvent>
{
    public Task HandleAsync(UserCreatedEvent notification, CancellationToken cancellationToken)
    {
        // React to user creation
        return Task.CompletedTask;
    }
}

Domain exceptions

DomainException is abstract and takes an Error — derive a concrete exception per invariant:

public sealed class UserNotFoundException : DomainException
{
    public UserNotFoundException(UserId userId)
        : base(Error.NotFound("User.NotFound", $"User {userId.Value} was not found"))
    { }
}