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
public sealed class UserId(Guid value)
{
public Guid Value { get; } = 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"))
{ }
}