ITLab.Template.DevPack.Guards
Custom Ardalis guard clause extensions for object equality, DateTimeOffset/TimeSpan comparisons, and DateOnly invariants.
Histórico: estas classes viviam em
Extensions/GuardExtensions.cs(arquivo único com três classes coabitando) até a versão 2.0.1. Movidas para a área dedicadaGuards/em 2.0.2 — namespaceITLab.Template.DevPack.Guards. VejaCHANGELOG.mdpara a nota de migração.
Componentes
| Tipo | Nome | Responsabilidade |
|---|---|---|
| Static Class | ObjectGuards | Generic equality guards: Equal<T>, NotEqual<T> |
| Static Class | DateTimeOffsetGuards | Comparison guards for DateTimeOffset and TimeSpan (LessThan, LessThanOrEqualTo, Greater/GreaterThan, GreaterThanOrEqualTo) and MustBeQuarterHourRounded |
| Static Class | DateOnlyGuards | Date invariants: NotFirstDayOfMonth, NotLastDayOfMonth |
| Static Class | DocumentGuards | Brazilian fiscal documents: InvalidCpf, InvalidCnpj (returns normalized digits-only on success) |
Como usar
using Ardalis.GuardClauses;
using ITLab.Template.DevPack.Guards;
// Object equality
Guard.Against.NotEqual(actualStatus, expectedStatus, nameof(actualStatus));
Guard.Against.Equal(value, forbiddenValue, nameof(value));
// DateTimeOffset / TimeSpan comparison
Guard.Against.LessThan(end, start, nameof(end)); // throws if end < start
Guard.Against.GreaterThanOrEqualTo(timeout, maxAllowed, nameof(timeout));
// Quarter-hour-rounded scheduling
var slot = Guard.Against.MustBeQuarterHourRounded(scheduledAt, nameof(scheduledAt));
// DateOnly invariants
Guard.Against.NotFirstDayOfMonth(billingCycleStart, nameof(billingCycleStart));
// Brazilian fiscal documents — guard returns the normalized digits-only value.
public Cpf(string raw)
{
Value = Guard.Against.InvalidCpf(raw, nameof(raw)); // throws ArgumentException if invalid
}
O que não fazer
- Do not throw
ArgumentExceptiondirectly when one of these guards covers the case — use the guard for consistent messages. - Do not catch
ArgumentExceptionfrom guards inside handlers; let it propagate to the pipeline boundary so the global exception handler maps it to a400 Bad Request. - Do not register
Guard.Againstextensions globally in DI — they are static methods onIGuardClause.
Extensão pelo produto
- Products can add product-specific guards in their own namespace (e.g.
MyApp.Guards) by declaring static extension classes onIGuardClause. Keep one class per concept. - The DevPack does not impose a discoverability mechanism beyond the
using ITLab.Template.DevPack.Guards;directive — consumers add the using only where they need the extensions.