Skip to content

A lightweight and easy-to-use library with entities that represents DDD concepts

License

Notifications You must be signed in to change notification settings

XerProjects/Xer.DomainDriven

Repository files navigation

Xer.DomainDriven

Domain Driven Design entities and marker interfaces.

Below are super basic examples on how to use the DDD types:

Aggregate Root:

public class OrderAggregateRoot : AggregateRoot
{
    private readonly List<LineItem> _lineItems;
  
    public OrderAggregateRoot (Guid orderId, IEnumerable<LineItem> lineItems)
        : base(orderId) // Pass ID to base.
    {
        _lineItems = lineItems.ToList();
    }

    public void Approve()
    {
        // Apply domain events to be committed and published by repository.
        // Include line item IDs in event.
        ApplyDomainEvent(new OrderApprovedEvent(Id, _lineItems.Select(li => li.Id)));
    }

    public void Cancel()
    {
        // Apply domain events to be committed and published by repository.
        // Include line item IDs in event.
        ApplyDomainEvent(new OrderCancelledEvent(Id, _lineItems.Select(li => li.Id)));
    }
}

Entity:

public class LineItem : Entity
{
    public string ProductName { get; }
    public string Description { get; }
    public Price Price { get; }
    
    public LineItem(Guid lineItemId, string productName, string description, Price price)
        : base(lineItemId) // Pass ID to base.
    {
        ProductName = productName;
        Description = description;
        Price = price;
    }
    
    public void ApplyDiscount(decimal discountPercentage)
    {
        Price = Price.ApplyDiscount(discountPercentage);
    }
}

Value Object:

public class Price : ValueObject<Price>
{
    public decimal Amount { get; }
    public string Currency { get; }
    
    public Price(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
    
    public Price AdjustAmount(decimal newAmount)
    {
        // Value objects should be immutable, so create a new instance.
        return new Price(newAmount, Currency);
    }
    
    public Price ApplyDiscount(decimal discountPercentage)
    {
        decimal discountedAmount = Price.Amount - (Price.Amount * discountPercentage);
        // Value objects should be immutable, so create a new instance.
        return new Price(discountedAmount, Currency);
    }
    
    public override bool ValueEquals(Price other)
    {
        return Amount == other.Amount &&
               Currency == other.Currency;
    }
    
    public override HashCode GenerateHashCode()
    {
        return HashCode.New.Combine(Amount)
                           .Combine(Currency);
    }
}