MarceloCastelo.IO.OutputEnvelop.FluentValidation
2.1.0
dotnet add package MarceloCastelo.IO.OutputEnvelop.FluentValidation --version 2.1.0
NuGet\Install-Package MarceloCastelo.IO.OutputEnvelop.FluentValidation -Version 2.1.0
<PackageReference Include="MarceloCastelo.IO.OutputEnvelop.FluentValidation" Version="2.1.0" />
<PackageVersion Include="MarceloCastelo.IO.OutputEnvelop.FluentValidation" Version="2.1.0" />
<PackageReference Include="MarceloCastelo.IO.OutputEnvelop.FluentValidation" />
paket add MarceloCastelo.IO.OutputEnvelop.FluentValidation --version 2.1.0
#r "nuget: MarceloCastelo.IO.OutputEnvelop.FluentValidation, 2.1.0"
#:package MarceloCastelo.IO.OutputEnvelop.FluentValidation@2.1.0
#addin nuget:?package=MarceloCastelo.IO.OutputEnvelop.FluentValidation&version=2.1.0
#tool nuget:?package=MarceloCastelo.IO.OutputEnvelop.FluentValidation&version=2.1.0
MCIO.OutputEnvelop.FluentValidation
Uma extensão do pacote MarceloCastelo.IO.OutputEnvelop que integra com o pacote FluentValidation.
📦 Pacotes
Nome | Versão | Link | Repository |
---|---|---|---|
MarceloCastelo.IO.OutputEnvelop | Nuget.org | Link | |
MarceloCastelo.IO.OutputEnvelop.FluentValidation | Nuget.org | Esse aqui 😃 |
🏷️ Labels
📄 Introdução
O pacote FluentValidation é amplamente utilizado em projetos .NET devido à sua robustez e flexibilidade, especialmente em validações de domínio. O pacote MarceloCastelo.IO.OutputEnvelop pode ser utilizado no lugar do FluentValidation. No entanto, é importante que eles possam funcionar lado a lado para proporcionar maior flexibilidade no projeto. Este pacote realiza a integração necessária para que possam coexistir harmoniosamente.
📖 Conteúdo
📦 Dependências
- .NET Standard 2.0.
- Pacote FluentValidation.
📚 Utilização básica
- Sem objeto de retorno
using MCIO.OutputEnvelop;
var validationResult = someValidator.Validate(input);
var outputEnvelop = validationResult.ToOutputEnvelop();
- Com objeto de retorno
using MCIO.OutputEnvelop;
var customer = new Customer();
var validationResult = someValidator.Validate(input);
var outputEnvelop = validationResult.ToOutputEnvelop(customer);
📚 Exemplo completo
public class Customer
{
// Fields
private static RegisterNewCustomerInputValidator _registerNewCustomerInputValidator = new();
// Properties
public int Id { get; }
public string Name { get; }
public DateOnly BirthDate { get; }
// Constructors
private Customer(int id, string name, DateOnly birthDate)
{
Id = id;
Name = name;
BirthDate = birthDate;
}
// Public Methods
// Validation result is a out variable for test reasons
public static OutputEnvelop<Customer> RegisterNew(RegisterNewCustomerInput input, out ValidationResult validationResult)
{
// Validation
validationResult = _registerNewCustomerInputValidator.Validate(input);
if (!validationResult.IsValid)
return validationResult.ToOutputEnvelop<Customer>(output: null!);
// Process and return
return validationResult.ToOutputEnvelop(
output: validationResult.IsValid ? new Customer(id: input.Id, name: input.Name, birthDate: input.BirthDate) : null!
);
}
// Inputs
public record RegisterNewCustomerInput(int Id, string Name, DateOnly BirthDate);
public class RegisterNewCustomerInputValidator
: AbstractValidator<RegisterNewCustomerInput>
{
// Constants
public const string CUSTOMER_ID_IS_REQUIRED_MESSAGE_CODE = "CUSTOMER_ID_IS_REQUIRED";
public const string CUSTOMER_ID_IS_REQUIRED_MESSAGE_DESCRIPTION = "Id is required";
public const Severity CUSTOMER_ID_IS_REQUIRED_MESSAGE_SEVERITY = Severity.Error;
public const string CUSTOMER_NAME_IS_REQUIRED_MESSAGE_CODE = "CUSTOMER_NAME_IS_REQUIRED";
public const string CUSTOMER_NAME_IS_REQUIRED_MESSAGE_DESCRIPTION = "Name is required";
public const Severity CUSTOMER_NAME_IS_REQUIRED_MESSAGE_SEVERITY = Severity.Error;
public const string CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_CODE = "CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME";
public const string CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_DESCRIPTION = "Name should have last name";
public const Severity CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_SEVERITY = Severity.Warning;
public const string CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_CODE = "CUSTOMER_BIRTHDATE_IS_REQUIRED";
public const string CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_DESCRIPTION = "BirthDate is required";
public const Severity CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_SEVERITY = Severity.Error;
public const string CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_CODE = "CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH";
public const string CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_DESCRIPTION = "BirthDate is required";
public const Severity CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_SEVERITY = Severity.Error;
public const string CUSTOMER_BIRTHDATE_DAY_MESSAGE_CODE = "CUSTOMER_BIRTHDATE_DAY";
public const string CUSTOMER_BIRTHDATE_DAY_MESSAGE_DESCRIPTION = "Today is the customer birthday";
public const Severity CUSTOMER_BIRTHDATE_DAY_MESSAGE_SEVERITY = Severity.Info;
// Public Methods
public RegisterNewCustomerInputValidator()
{
RuleFor(p => p.Id)
.GreaterThan(0)
.WithErrorCode(CUSTOMER_ID_IS_REQUIRED_MESSAGE_CODE)
.WithMessage(CUSTOMER_ID_IS_REQUIRED_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_ID_IS_REQUIRED_MESSAGE_SEVERITY);
RuleFor(p => p.Name)
.NotEmpty()
.WithErrorCode(CUSTOMER_NAME_IS_REQUIRED_MESSAGE_CODE)
.WithMessage(CUSTOMER_NAME_IS_REQUIRED_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_NAME_IS_REQUIRED_MESSAGE_SEVERITY);
RuleFor(p => p.Name)
.MaximumLength(150)
.WithErrorCode("CUSTOMER_NAME_SHOULD_HAVE_MAX_LENGTH")
.WithMessage("Name should less than or equais 150 characters")
.WithSeverity(Severity.Error);
RuleFor(p => p.Name)
.Must(name => name.Contains(" "))
.WithErrorCode(CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_CODE)
.WithMessage(CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_NAME_SHOULD_HAVE_LAST_NAME_MESSAGE_SEVERITY);
RuleFor(p => p.BirthDate)
.NotEmpty()
.WithErrorCode(CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_CODE)
.WithMessage(CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_BIRTHDATE_IS_REQUIRED_MESSAGE_SEVERITY);
RuleFor(p => p.BirthDate)
.LessThanOrEqualTo(DateOnly.FromDateTime(DateTime.Now))
.WithErrorCode(CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_CODE)
.WithMessage(CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_BIRTHDATE_SHOULD_HAVE_MAX_LENGTH_MESSAGE_SEVERITY);
RuleFor(p => p.BirthDate)
.Must(q => q != DateOnly.FromDateTime(DateTime.Now))
.WithErrorCode(CUSTOMER_BIRTHDATE_DAY_MESSAGE_CODE)
.WithMessage(CUSTOMER_BIRTHDATE_DAY_MESSAGE_DESCRIPTION)
.WithSeverity(CUSTOMER_BIRTHDATE_DAY_MESSAGE_SEVERITY);
}
}
}
🚀 Executando localmente
Por se tratar de um pacote nuget, não existe uma execução. Porém, existe o script build-local-script que pode ser executado via PowerShell que realizará as seguintes ações:
- Instalará a CLI do ReportGenerator localmente para visualização do relatório de cobertura no formato opencover.
- Instalará a CLI do Stryker localmente para execução e visualização do relatório do teste de mutação.
- Restore do projeto.
- Build do projeto em modo release.
- Execução dos testes de unidade.
- Execução do teste de mutação.
- Abertura do relatório de cobertura no navegador web padrão.
- Abertura do relatório de teste mutante no navegador web padrão.
A partir do diretóio raiz
do repositório, no PowerShell
, execute o comando .\build-local-script.ps1
.
Caso queira limpar todos os arquivos gerados, a partir do diretóio raiz
do repositório, no PowerShell
, execute o comando .\clear-local-script.ps1
.
🚀 Benchmark
O benchmark abaixo (arquivo ExtensionMethodsBenchmark.cs) compara a utilização do objeto ValidationResult como retorno do método e gerando um OutputEnvelop a partir do ValidationResult gerado.
// * Summary *
BenchmarkDotNet v0.13.11, Windows 11 (10.0.22631.2861/23H2/2023Update/SunValley3)
AMD Ryzen 5 5600X, 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.100
[Host] : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
Job-BHOBUW : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
LaunchCount=1 RunStrategy=Throughput
Method | Mean | Error | StdDev | Ratio | RatioSD | TotalCycles/Op | CacheMisses/Op | BranchInstructions/Op | TotalIssues/Op | BranchMispredictions/Op | Timer/Op | Gen0 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
'ValidationResult From Valid Input' | 2.126 us | 0.0149 us | 0.0140 us | 1.00 | 0.00 | 4,955 | 10 | 1,754 | 7,701 | 7 | 21 | 0.0381 | 664 B | 1.00 |
'OutputEnvelop From Valid Input' | 2.142 us | 0.0094 us | 0.0088 us | 1.01 | 0.01 | 4,969 | 11 | 1,775 | 7,748 | 7 | 22 | 0.0381 | 664 B | 1.00 |
'ValidationResult From Invalid Input' | 3.951 us | 0.0223 us | 0.0198 us | 1.86 | 0.02 | 9,076 | 29 | 3,289 | 14,827 | 16 | 40 | 0.1297 | 2224 B | 3.35 |
'OutputEnvelop From Invalid Input' | 4.048 us | 0.0152 us | 0.0127 us | 1.90 | 0.01 | 9,332 | 30 | 3,410 | 15,154 | 17 | 41 | 0.1373 | 2320 B | 3.49 |
// * Hints *
Outliers
ExtensionMethodsBenchmark.'OutputEnvelop From Valid Input': LaunchCount=1, RunStrategy=Throughput -> 1 outlier was detected (2.12 us)
ExtensionMethodsBenchmark.'ValidationResult From Invalid Input': LaunchCount=1, RunStrategy=Throughput -> 1 outlier was removed (4.01 us)
ExtensionMethodsBenchmark.'OutputEnvelop From Invalid Input': LaunchCount=1, RunStrategy=Throughput -> 2 outliers were removed (4.16 us, 4.19 us)
🧑🤝🧑 Contribuindo
Você está mais que convidado para constribuir. Caso tenha interesse e queira participar do projeto, não deixe de ver nosso manual de contribuição.
🧑🤝🧑 Autores
- Marcelo Castelo Branco - @MarceloCas
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- FluentValidation (>= 11.9.0)
- MarceloCastelo.IO.OutputEnvelop (>= 2.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|