Domain-Driven Design - Value Objects in C#
Before you look at the Value Objects example in C#, you can see at my post on what Value Objects are in Domain-Driven Design.
Value Object base class in C#
public abstract record ValueObject<T> : IEquatable<T> where T : IEquatable<T>
{
protected T Value { get; }
protected ValueObject(T value)
{
this.Validate(value);
this.Value = value;
}
protected abstract void Validate(T value);
public bool Equals(T? other)
{
return this.Value.Equals(other);
}
public static bool operator ==(ValueObject<T> a, T b) => a.Equals(b);
public static bool operator !=(ValueObject<T> a, T b) => !a.Equals(b);
}
About this code snippet:
- It is a
record
: Records (C# 9) are primarily built for better supporting immutable data models. - It is
abstract
: This prevents this record from being instantiated and allows to declare abstract methods. T
extends fromIEquatable
:T
is the basic value type of the Value Object, so ifT
extends fromIEquatable
, it forces that basic value type of the Value Object to be equatable.- It extends from
IEquatable<T>
: Allows comparing this Value Object with its basic data type. - It calls an abstract method called Validate in the constructor: So we are validating the value of the Value Object before creating it.
Value Object example in C#
public sealed record FirstName : ValueObject<string>
{
public const UInt16 MaxLength = 50;
public string Name => this.Value;
private FirstName(string value) : base(value)
{
}
public static FirstName Create(string value)
{
return new FirstName(value);
}
protected override void Validate(string value)
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException(nameof(value));
if (value.Length > FirstName.MaxLength)
throw new ArgumentOutOfRangeException(nameof(value));
}
}
About this code snippet:
- It is
sealed
: Prevent another class from extends from this one. - It overrides the Validate method with validation rules.
- No public
constructor
: Other classes cannot create instances of this class, except for nested classes. - To create instances of this Value Object we do not call the constructor directly, but it uses the Static Factory Method pattern instead.
Categories
Automation scripting Development tools Front end web development Infrastructure Kubernetes Programming guide Security Software architectureTags
Recent Posts
Restart Kubernetes pods following a schedule using Helm
Restart Kubernetes pods following a schedule using Kubectl
Create an Azure Key Vault with RBAC role assignments using Terraform
Get the download url of the latest GitHub release using Bash
Get the download url of the latest GitHub release using PowerShell