A comprehensive .NET solution providing foundational libraries and utilities for building modern, maintainable applications following Domain-Driven Design (DDD) principles and best practices.
Slo248.Net.Basis is a collection of NuGet packages designed to accelerate .NET development with proven architectural patterns, abstractions, and utilities. It focuses on providing clean, reusable, and production-ready components for enterprise applications.
A lightweight, production-ready Domain-Driven Design library for .NET 10.0+ providing foundational abstractions and base classes for building robust domain models using DDD principles.
Key Features:
- Generic, type-safe Aggregate Root and Entity base classes with dual generic parameters
- Value Objects with atomic value composition and value-based equality
- Domain event management and event sourcing support
- Repository pattern abstractions
- MediatR integration for event handling
- Strongly-typed, reusable entity identifiers with implicit conversions
Installation:
dotnet add package Slo248.Net.DDDusing Slo248.Net.DDD.Models;
public class Order : AggregateRoot<Guid, Order>
{
private readonly List<OrderItem> _items = [];
public IReadOnlyList<OrderItem> Items => _items.AsReadOnly();
public OrderStatus Status { get; private set; }
public Order(EntityId<Guid, Order> id) : base(id)
{
Status = OrderStatus.Pending;
}
public Order() : base() // Auto-generates Guid
{
Status = OrderStatus.Pending;
}
public void AddItem(OrderItem item)
{
_items.Add(item);
RaiseDomainEvent(new OrderItemAddedEvent(Id.Value, item.ProductId, item.Quantity));
}
}
public enum OrderStatus { Pending, Completed, Cancelled }using MediatR;
using Slo248.Net.DDD.Models;
using Slo248.Net.DDD.Services;
public record OrderItemAddedEvent(Guid OrderId, Guid ProductId, int Quantity) : IDomainEvent;
public class DomainEventPublisher : IDomainEventPublisher
{
private readonly IMediator _mediator;
public DomainEventPublisher(IMediator mediator) => _mediator = mediator;
public async Task Publish(IDomainEvent[] events, CancellationToken cancellationToken = default)
{
foreach (var domainEvent in events)
{
await _mediator.Publish((dynamic)domainEvent, cancellationToken);
}
}
}
public class OrderItemAddedEventHandler : INotificationHandler<OrderItemAddedEvent>
{
public async Task Handle(OrderItemAddedEvent notification, CancellationToken cancellationToken)
{
// Handle the order item added event
await Task.CompletedTask;
}
}- .NET 10.0 or later
- (Optional) MediatR 12.0 or later – for event handling integration
The Slo248.Net.Basis solution follows these architectural principles:
- Domain-Driven Design – Clean, cohesive domain models with proper separation of concerns
- SOLID Principles – Maintainable, testable, and extensible code
- Repository Pattern – Data access abstraction with event sourcing support
- Event-Driven Architecture – Decoupled, scalable communication patterns via domain events
- Strongly-Typed Identifiers – Generic, reusable
EntityId<TId, TEntity>for type-safe ID management - Value Objects – Immutable objects with value-based equality and atomic composition
- Event Sourcing – Track and manage uncommitted events for eventual consistency patterns
Slo248.Net.Basis/
├── Slo248.Net.DDD/ # Core DDD library (NuGet package)
│ ├── Models/ # Base classes and interfaces
│ └── Services/ # Repository and event abstractions
└── Slo248.Tests/ # Unit tests for DDD library
| Package | Description | Status |
|---|---|---|
| Slo248.Net.DDD | DDD patterns and abstractions |
-
Install the NuGet package:
dotnet add package Slo248.Net.DDD
-
Define your domain models:
- Create aggregate roots inheriting from
AggregateRoot<TId, TEntity>orAggregateRoot<TEntity>(for Guid) - Create child entities inheriting from
Entity<TId, TEntity>orEntity<TEntity> - Use
EntityId<TId, TEntity>for strongly-typed identifiers, orEntityId<TEntity>for Guid-based IDs
- Create aggregate roots inheriting from
-
Define domain events:
- Create records implementing
IDomainEvent - Raise them using
RaiseDomainEvent()in your aggregates - Track uncommitted events with
GetUncommittedEvents()
- Create records implementing
-
Handle events after persistence:
- Implement
IDomainEventPublisheror use the MediatR integration - Call
MarkAsCommitted()on the aggregate after event publication
- Implement
-
Implement repositories:
- Create repository classes implementing
IRepository<TAggregateRoot, TId> - Publish events before or after persistence based on your consistency requirements
- Create repository classes implementing
Contributions are welcome! To contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details
For issues, questions, or suggestions:
- 📝 Open an issue on GitHub
- 💬 Start a discussion
- 📧 Contact the maintainers
Built with ❤️ for the .NET community