HexMaster.DomainDrivenDesign
3.0.0
dotnet add package HexMaster.DomainDrivenDesign --version 3.0.0
NuGet\Install-Package HexMaster.DomainDrivenDesign -Version 3.0.0
<PackageReference Include="HexMaster.DomainDrivenDesign" Version="3.0.0" />
paket add HexMaster.DomainDrivenDesign --version 3.0.0
#r "nuget: HexMaster.DomainDrivenDesign, 3.0.0"
// Install HexMaster.DomainDrivenDesign as a Cake Addin #addin nuget:?package=HexMaster.DomainDrivenDesign&version=3.0.0 // Install HexMaster.DomainDrivenDesign as a Cake Tool #tool nuget:?package=HexMaster.DomainDrivenDesign&version=3.0.0
Domain Driven Design Support Library
Welcome to the Domain Driven Design Support Library, a NuGet package designed to simplify the implementation of Domain-Driven Design (DDD) in your projects. This library abstracts away the base plumbing required for DDD, allowing you to focus on your core domain logic.
Key Features
- Provides the essential
IDomainModel
interface to define domain models. - Includes a base implementation
DomainModel<T>
to streamline common operations for domain models. - Supports domain events with built-in event handling and dispatching mechanisms.
- Helps you adhere to DDD principles while reducing boilerplate code.
- Highly extensible and ready to integrate into existing DDD-based architectures.
Getting Started
Installation
Add the NuGet package to your project:
Install-Package HexMaster.DomainDrivenDesign
Usage
1. Implementing Domain Models
The core of this library is the IDomainModel
interface. It provides the foundation for all domain models in your application.
For most use cases, you can inherit from the DomainModel<T>
base class, which already implements IDomainModel
and provides useful base functionality.
Example
Here's an example of creating a domain model for an Order
entity:
using HexMaster.DomainDrivenDesign;
public class Order : DomainModel<Guid>
{
public string CustomerName { get; private set; }
public DateTime OrderDate { get; private set; }
public Order(Guid id, string customerName, DateTime orderDate) : base(id)
{
CustomerName = customerName;
OrderDate = orderDate;
}
public void UpdateCustomerName(string newCustomerName)
{
if (string.IsNullOrWhiteSpace(newCustomerName))
throw new ArgumentException("Customer name cannot be empty.");
CustomerName = newCustomerName;
}
}
2. Base Class Benefits
The DomainModel<T>
base class simplifies your domain model by:
- Enforcing an ID property of type
T
. - Ensuring equality checks based on the ID.
- Abstracting away common domain logic.
Example Base Class Functionality
Order order1 = new Order(Guid.NewGuid(), "John Doe", DateTime.UtcNow);
Order order2 = new Order(order1.Id, "John Doe", DateTime.UtcNow);
// Equality check based on ID
Console.WriteLine(order1 == order2); // True
Domain Events
Domain events are a key concept in Domain-Driven Design, allowing you to capture and react to significant changes or events within your domain. This library provides built-in support for domain events, enabling easy integration and handling.
IDomainEvent Interface
All domain events in this library must implement the IDomainEvent
interface. This interface represents an event that has occurred within your domain.
public interface IDomainEvent
{
DateTime OccurredOn { get; }
}
Raising Domain Events
The DomainModel<T>
base class includes a method AddDomainEvent
for raising domain events. These events can be processed later by the Domain Event Dispatcher.
Example
using HexMaster.DomainDrivenDesign;
public class Order : DomainModel<Guid>
{
public string CustomerName { get; private set; }
public Order(Guid id, string customerName) : base(id)
{
CustomerName = customerName;
}
public void PlaceOrder()
{
// Raise a domain event
AddDomainEvent(new OrderPlacedEvent(Id));
}
}
public class OrderPlacedEvent : IDomainEvent
{
public Guid OrderId { get; }
public DateTime OccurredOn { get; } = DateTime.UtcNow;
public OrderPlacedEvent(Guid orderId)
{
OrderId = orderId;
}
}
Domain Event Dispatcher
The Domain Event Dispatcher processes and dispatches domain events to their corresponding handlers. It integrates with Dependency Injection (DI) to resolve and invoke event handlers automatically.
Enabling the Dispatcher
To use the Domain Event Dispatcher, register it in your application startup:
services.AddDomainEventDispatcher();
Handling Domain Events
Event handlers process domain events when they are dispatched. Handlers must inherit from the DomainEventHandler<TEvent>
base class, where TEvent
is the type of domain event to handle.
The DomainEventHandler<TEvent>
base class provides an abstract Handle
method that you override to define your handling logic.
Example
using DDD.Support.Library;
using System.Threading.Tasks;
public class OrderPlacedEventHandler : DomainEventHandler<OrderPlacedEvent>
{
public override Task Handle(OrderPlacedEvent domainEvent)
{
// Handle the event (e.g., send an email, update a database, etc.)
Console.WriteLine($"Order placed with ID: {domainEvent.OrderId}");
return Task.CompletedTask;
}
}
Complete Workflow
- Raise a domain event using
AddDomainEvent
in your domain model. - Register the Domain Event Dispatcher in your application startup.
- Implement event handlers by inheriting from
DomainEventHandler<TEvent>
and overriding theHandle
method. - When the domain event is raised, the dispatcher will resolve the appropriate handler(s) and invoke the
Handle
method.
Interfaces and Classes
IDomainModel
The IDomainModel
interface is the contract for all domain models in your application. It ensures that all domain models have an ID and enforce a basic equality structure.
public interface IDomainModel
{
object Id { get; }
}
DomainModel<T>
The DomainModel<T>
class provides a base implementation of IDomainModel
and includes:
- A strongly-typed ID property.
- Overridden equality methods (
Equals
,GetHashCode
,==
,!=
). - A constructor that enforces the initialization of the ID.
- Support for raising domain events through
AddDomainEvent
.
public abstract class DomainModel<T> : IDomainModel
{
public T Id { get; }
private readonly List<IDomainEvent> _domainEvents = new();
public IReadOnlyCollection<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
protected DomainModel(T id)
{
if (id == null || id.Equals(default(T)))
throw new ArgumentException("ID cannot be null or default.");
Id = id;
}
protected void AddDomainEvent(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public void ClearDomainEvents() => _domainEvents.Clear();
public override bool Equals(object obj)
{
if (obj is DomainModel<T> other)
{
return EqualityComparer<T>.Default.Equals(Id, other.Id);
}
return false;
}
public override int GetHashCode() => EqualityComparer<T>.Default.GetHashCode(Id);
public static bool operator ==(DomainModel<T> a, DomainModel<T> b) =>
a?.Equals(b) ?? b is null;
public static bool operator !=(DomainModel<T> a, DomainModel<T> b) => !(a == b);
object IDomainModel.Id => Id;
}
Extending the Library
If the DomainModel<T>
class does not meet your specific requirements, you can:
- Implement the
IDomainModel
interface directly. - Extend
DomainModel<T>
with additional functionality.
Contributing
Contributions are welcome! Feel free to submit issues, feature requests, or pull requests on the GitHub repository.
License
This project is licensed under the MIT License. See the LICENSE
file for details.
Feedback and Support
If you encounter any issues or have suggestions, please open an issue on GitHub or contact the maintainers directly.
Start building your next Domain-Driven Design project with confidence using the Domain Driven Design Support Library!
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Cryptography.KeyDerivation (>= 8.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on HexMaster.DomainDrivenDesign:
Package | Downloads |
---|---|
TinyLink.ShortLinks
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
3.0.0 | 65 | 2/6/2025 |
2.0.23 | 29 | 2/5/2025 |
2.0.22 | 58 | 2/5/2025 |
2.0.20 | 31 | 2/5/2025 |
2.0.19 | 37 | 2/5/2025 |
2.0.18 | 33 | 2/5/2025 |
2.0.17 | 37 | 2/5/2025 |
2.0.16 | 31 | 2/5/2025 |
2.0.13 | 37 | 2/5/2025 |
2.0.12 | 26 | 2/5/2025 |
2.0.11 | 29 | 2/5/2025 |
2.0.10 | 31 | 2/5/2025 |
2.0.7 | 691 | 11/8/2024 |
2.0.5 | 862 | 8/11/2023 |
2.0.4 | 168 | 8/10/2023 |
2.0.3 | 153 | 8/10/2023 |
2.0.2 | 154 | 8/10/2023 |
2.0.0 | 690 | 11/11/2022 |
1.0.2 | 866 | 6/1/2022 |
1.0.1 | 436 | 5/30/2022 |
1.0.0 | 430 | 5/19/2022 |
0.1.24 | 428 | 5/19/2022 |
0.1.23 | 349 | 11/10/2021 |
0.1.20 | 334 | 11/4/2021 |
0.1.19 | 329 | 11/4/2021 |
0.1.18 | 342 | 11/4/2021 |
0.1.17 | 360 | 11/4/2021 |
0.0.4 | 330 | 11/4/2021 |
0.0.3 | 386 | 11/3/2021 |
0.0.2 | 345 | 10/21/2021 |
0.0.1 | 337 | 10/21/2021 |