Skip to content

mateusseger/MStack.ValueObjects

Repository files navigation

MStack.ValueObjects

DDD value object base classes plus a curated set of common value objects (Email, Slug, Money, Cpf, Cnpj, Document, Cep, PhoneNumberBr). Construction returns Result<T> so failures compose naturally with the rest of your code.

NuGet License: MIT


Why

Problem What this package gives you
Re-implementing Equals / GetHashCode for every primitive wrapper ValueObject and SingleValueObject<T> base classes — define GetEqualityComponents and you're done.
Throwing exceptions during construction Each common VO returns Result<T> from MStack.ErrorHandling. Failures stay in the Result pipeline.
Re-writing CPF / CNPJ / CEP / Phone validation Production-tested implementations included.

Install

dotnet add package MStack.ValueObjects

This brings MStack.ErrorHandling along.

Quick start

Roll your own value object

using MStack.ErrorHandling;

namespace MyApp;

public sealed class Coordinates : ValueObject
{
    public double Latitude { get; }
    public double Longitude { get; }

    private Coordinates(double lat, double lng)
    {
        Latitude = lat;
        Longitude = lng;
    }

    public static Result<Coordinates> Create(double lat, double lng)
    {
        if (lat is < -90 or > 90)
        {
            return Error.Validation(nameof(Latitude), "Must be between -90 and 90.");
        }

        if (lng is < -180 or > 180)
        {
            return Error.Validation(nameof(Longitude), "Must be between -180 and 180.");
        }

        return new Coordinates(lat, lng);
    }

    protected override IEnumerable<object?> GetEqualityComponents()
    {
        yield return Latitude;
        yield return Longitude;
    }
}

Or use the included VOs

using MStack.ValueObjects;

var emailResult = Email.Create("user@example.com");
var cpfResult   = Cpf.Create("390.533.447-05");
var cnpjResult  = Cnpj.Create("11.222.333/0001-81");
var docResult   = Document.Create("390.533.447-05");   // CPF or CNPJ
var cepResult   = Cep.Create("01310-100");
var phoneResult = PhoneNumberBr.Create("(11) 91234-5678");
var moneyResult = Money.Create(99.90m, "BRL");
var slugResult  = Slug.Create("hello-world");

if (emailResult.IsFailure) { /* errors live in result.Errors */ }

Failures are categorised as ErrorCategory.Validation, so MStack.ErrorHandling will turn them into a 400 Bad Request ProblemDetails automatically when used in a Minimal API.


What ships

Type Namespace Notes
ValueObject MStack.ValueObjects Abstract base. Override GetEqualityComponents.
SingleValueObject<T> MStack.ValueObjects Helper for VOs wrapping one value. Provides Value, ToString(), implicit operator T, and GetEqualityComponents.
Email MStack.ValueObjects Trim + lowercase, RFC-shaped regex.
Slug MStack.ValueObjects Lowercase letters, digits and single hyphens.
Money MStack.ValueObjects Decimal + ISO 4217 currency. Add requires same currency.
Cpf MStack.ValueObjects Brazilian CPF, full check-digit validation.
Cnpj MStack.ValueObjects Brazilian CNPJ, full check-digit validation.
Document MStack.ValueObjects CPF or CNPJ — auto-detected by length.
Cep MStack.ValueObjects Brazilian postal code, 8 digits.
PhoneNumberBr MStack.ValueObjects Brazilian phone, 10 or 11 digits. Rejects toll-free (0800). Includes ToE164().

VOs that inherit from SingleValueObject<T> expose Value (raw digits/string), ToFormatted() where formatting makes sense, implicit conversion to the underlying type, and structural equality. Those inheriting directly from ValueObject expose their own domain-specific properties.


License

MIT

About

Value Object base classes for DDD plus a curated set of ready-to-use value objects (Email, Slug, Money, Cpf, Cnpj, Cep, PhoneNumberBr...). Construction returns Result<T> from MStack.ErrorHandling so failures compose naturally with the rest of your application.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages