Nuuvify.CommonPack.Extensions
2.2.0-test.25102902
See the version list below for details.
dotnet add package Nuuvify.CommonPack.Extensions --version 2.2.0-test.25102902
NuGet\Install-Package Nuuvify.CommonPack.Extensions -Version 2.2.0-test.25102902
<PackageReference Include="Nuuvify.CommonPack.Extensions" Version="2.2.0-test.25102902" />
<PackageVersion Include="Nuuvify.CommonPack.Extensions" Version="2.2.0-test.25102902" />
<PackageReference Include="Nuuvify.CommonPack.Extensions" />
paket add Nuuvify.CommonPack.Extensions --version 2.2.0-test.25102902
#r "nuget: Nuuvify.CommonPack.Extensions, 2.2.0-test.25102902"
#:package Nuuvify.CommonPack.Extensions@2.2.0-test.25102902
#addin nuget:?package=Nuuvify.CommonPack.Extensions&version=2.2.0-test.25102902&prerelease
#tool nuget:?package=Nuuvify.CommonPack.Extensions&version=2.2.0-test.25102902&prerelease
Nuuvify.CommonPack.Extensions
Biblioteca fundamental com implementação do Notification Pattern e extensões utilitárias essenciais. Fornece uma base sólida para aplicações .NET com tratamento padronizado de notificações, extensões para strings, coleções, enums e outros tipos comuns.
📋 Índice
- Nuuvify.CommonPack.Extensions
- 📋 Índice
- Funcionalidades
- Instalação
- Dependências
- Configuração
- Uso
- Exemplos Práticos
- API Reference
- Troubleshooting
- Changelog
- 📞 Suporte
Funcionalidades
- ✅ Notification Pattern para tratamento padronizado de erros e validações
- ✅ String Extensions com manipulação de caracteres especiais e formatação
- ✅ Enum Extensions com conversões e descrições automáticas
- ✅ Domain Entity classe base para entidades de domínio
- ✅ JSON Extensions com conversores customizados
- ✅ DateTime Extensions para manipulações de data/hora
- ✅ Dictionary Extensions para operações em dicionários
- ✅ Object Extensions para reflexão e validações
- ✅ PathHelper para manipulação e validação de caminhos cross-platform
- ✅ Logging Integration com Microsoft.Extensions.Logging
- ✅ Data Annotations com validações customizadas
- ✅ Compatibilidade .NET Standard 2.1 para máxima portabilidade
Instalação
Via Package Manager Console
Install-Package Nuuvify.CommonPack.Extensions
Via .NET CLI
dotnet add package Nuuvify.CommonPack.Extensions
Via PackageReference
<PackageReference Include="Nuuvify.CommonPack.Extensions" Version="X.X.X" />
Dependências
NuGet Packages
| Package | Version | Descrição |
|---|---|---|
| Microsoft.CSharp | 4.7.0 | Suporte para recursos do C# como dynamic e interpolação de strings |
| System.ComponentModel.Annotations | 5.0.0 | Data Annotations para validação de modelos |
| System.Runtime.Extensions | 4.3.1 | Extensões fundamentais do runtime .NET |
| System.Diagnostics.DiagnosticSource | 8.0.1 | Infraestrutura para diagnósticos e observabilidade |
| Microsoft.Extensions.Logging.Abstractions | 8.0.3 | Abstrações do sistema de logging |
| Microsoft.Extensions.Logging.Configuration | 8.0.1 | Configuração para sistema de logging |
| Microsoft.Extensions.Logging.Console | 8.0.1 | Provider de console para logging |
| Microsoft.Extensions.Logging | 8.0.1 | Sistema de logging unificado |
| Microsoft.Extensions.Options | 8.0.2 | Padrão Options para configuração |
| System.Text.Json | 8.0.5 | Serialização/deserialização JSON de alta performance |
Framework
- .NET Standard 2.1: Garante compatibilidade com .NET Core 3.0+, .NET 5+, .NET 6+, .NET 8+ e .NET Framework 4.7.2+
Configuração
Esta biblioteca não requer configuração específica para uso básico. Para recursos de logging:
// Program.cs ou Startup.cs
using Microsoft.Extensions.Logging;
// Configurar logging (opcional)
builder.Services.AddLogging(configure => configure.AddConsole());
Uso
Notification Pattern
NotifiableR - Classe Base
public class PessoaService : NotifiableR
{
public void ValidarPessoa(string nome, int idade)
{
if (string.IsNullOrEmpty(nome))
{
AddNotification("Nome", "Nome é obrigatório");
}
if (idade < 18)
{
AddNotification("Idade", "Pessoa deve ser maior de idade");
}
// Verificar se há erros
if (!IsValid())
{
// Processar notificações
foreach (var notification in Notifications)
{
Console.WriteLine($"{notification.Property}: {notification.Message}");
}
}
}
public void ProcessarComLog(ILogger logger)
{
// Validações que podem gerar notificações
ValidarPessoa("", 15);
// Log automático das notificações
var notifications = LoggerNotifications(logger, "ProcessarComLog");
// As notificações são automaticamente logadas como Warning
}
}
NotificationR - Estrutura de Notificação
public class ValidationService : NotifiableR
{
public void ProcessarDados(List<string> dados)
{
for (int i = 0; i < dados.Count; i++)
{
if (string.IsNullOrEmpty(dados[i]))
{
// Adicionar notificação com ID do agregado
AddNotification("Dados", $"Item {i} está vazio", aggregateId: i.ToString());
}
}
// Remover notificações específicas se necessário
if (dados.Count > 100)
{
RemoveNotification("Dados");
}
// Limpar todas as notificações
RemoveNotifications(removeAll: true);
}
public void AdicionarNotificacoesExternas(IList<NotificationR> notificacoesExternas)
{
// Adicionar notificações de outros serviços
AddNotifications(notificacoesExternas);
}
}
String Extensions
Manipulação de Caracteres Especiais
using Nuuvify.CommonPack.Extensions.Implementation;
public class TextProcessingService
{
public void ProcessarTextos()
{
string textoComEspeciais = "João & Maria - R$ 1.500,00!";
// Remover caracteres especiais (mantém apenas ASCII 20-7E)
string limpo = textoComEspeciais.RemoveSpecialChars();
// Resultado: "Joo Maria R 1500"
// Manter apenas letras e números
string alphanumerico = textoComEspeciais.GetLettersAndNumbersOnly();
// Resultado: "JooMaria1500"
// Remover acentos mas manter estrutura
string semAcentos = "José María Piñón".RemoveAccent();
// Resultado: "Jose Maria Pinon"
// Extrair apenas números
string apenasNumeros = "ABC-123-DEF-456".GetNumbers();
// Resultado: "123456"
}
public void FormatacaoSegura()
{
string texto = null;
// Métodos seguros que não geram NullReferenceException
string upper = texto.ToUpperNotNull(); // Retorna null
string lower = texto.ToLowerNotNull(); // Retorna null
string trimmed = texto.TrimNotNull(); // Retorna null
// Ao invés de:
// string upper = texto?.ToUpper(); // Syntax mais verbosa
}
}
Formatação e Conversão
public class FormattingService
{
public void ExemplosFormatacao()
{
// Conversão para Title Case
string nome = "joão da silva";
string titleCase = StringExtensionMethods.ToTitleCase(nome);
// Resultado: "João Da Silva"
// Limpeza mantendo alguns caracteres
string codigo = "ABC-123_DEF@456";
string limpo = codigo.RemoveCharsKeepChars("-", "_");
// Resultado: "ABC-123_DEF456"
// Limpeza mantendo diacríticos (acentos)
string textoAcentuado = "José & María!";
string mantendoAcentos = textoAcentuado.RemoveCharsKeepDiacritics();
// Resultado: "José María"
}
}
Enum Extensions
Conversões e Descrições
using System.ComponentModel;
using Nuuvify.CommonPack.Extensions.Implementation;
public enum StatusPedido
{
[Description("Aguardando Pagamento")]
AguardandoPagamento = 1,
[Description("Pagamento Confirmado")]
PagamentoConfirmado = 2,
[Description("Em Preparação")]
EmPreparacao = 3
}
public class PedidoService
{
public void ProcessarEnums()
{
var status = StatusPedido.AguardandoPagamento;
// Obter descrição do enum
string descricao = status.GetDescription();
// Resultado: "Aguardando Pagamento"
// Converter string para número do enum
string statusTexto = "PagamentoConfirmado";
int numeroEnum = statusTexto.ToEnumNumero<StatusPedido>();
// Resultado: 2
// Converter número para texto do enum
int numero = 3;
string textoEnum = numero.ToEnumTexto<StatusPedido>();
// Resultado: "EmPreparacao"
// Verificar se string é um enum válido
bool isValid = "StatusInvalido".IsEnum<StatusPedido>(out int resultado);
// Resultado: false, resultado = int.MaxValue
}
}
Domain Entity
Classe Base para Entidades
public class ProdutoEntity : DomainEntity
{
public string Nome { get; private set; }
public decimal Preco { get; private set; }
public bool Ativo { get; private set; }
public ProdutoEntity(string nome, decimal preco)
{
// Id já é gerado automaticamente no constructor base
Nome = nome;
Preco = preco;
Ativo = true;
// Propriedades de auditoria são preenchidas automaticamente:
// - DataCadastro
// - UsuarioCadastro (preenchido pelo SaveChanges do repository)
}
public void AtualizarPreco(decimal novoPreco)
{
Preco = novoPreco;
// DataAlteracao e UsuarioAlteracao serão preenchidos pelo SaveChanges
}
// Sobrescrever propriedades de auditoria se necessário
[JsonIgnore]
public override DateTimeOffset DataCadastro => base.DataCadastro;
}
// Uso
public class ProdutoService : NotifiableR
{
public ProdutoEntity CriarProduto(string nome, decimal preco)
{
if (string.IsNullOrEmpty(nome))
{
AddNotification("Nome", "Nome do produto é obrigatório");
return null;
}
if (preco <= 0)
{
AddNotification("Preco", "Preço deve ser maior que zero");
return null;
}
return new ProdutoEntity(nome, preco);
}
}
JSON Extensions
Conversores Customizados
using System.Text.Json;
using Nuuvify.CommonPack.Extensions.JsonConverter;
public class ConfigurationService
{
public void SerializacaoPersonalizada()
{
var produto = new ProdutoEntity("Notebook", 2500.00m);
var options = new JsonSerializerOptions
{
WriteIndented = true,
Converters = {
new NullToDefaultValueConverter() // Converte nulls para valores padrão
}
};
string json = JsonSerializer.Serialize(produto, options);
// NullToDefaultValueConverter converte propriedades null para valores padrão:
// - string null → ""
// - int? null → 0
// - DateTime? null → DateTime.MinValue
}
}
DateTime Extensions
using Nuuvify.CommonPack.Extensions.Implementation;
public class AgendaService
{
public void ManipulacoesData()
{
var agora = DateTime.Now;
// Extensões para DateTime (exemplos conceituais)
// As implementações específicas dependem dos métodos disponíveis na biblioteca
// Formatação segura
DateTime? dataOpcional = null;
string dataFormatada = dataOpcional.ToStringNotNull(); // Retorna null ao invés de exception
}
}
Exemplos Práticos
Exemplo 1: Validação de Formulário com Notifications
public class UsuarioService : NotifiableR
{
public UsuarioEntity CriarUsuario(CriarUsuarioCommand command)
{
// Validar nome
if (string.IsNullOrWhiteSpace(command.Nome))
{
AddNotification("Nome", "Nome é obrigatório");
}
else if (command.Nome.Length < 2)
{
AddNotification("Nome", "Nome deve ter pelo menos 2 caracteres");
}
// Validar email usando extension
var emailLimpo = command.Email?.TrimNotNull()?.ToLowerNotNull();
if (string.IsNullOrEmpty(emailLimpo) || !IsValidEmail(emailLimpo))
{
AddNotification("Email", "Email inválido");
}
// Validar idade
if (command.Idade < 18)
{
AddNotification("Idade", "Usuário deve ser maior de idade");
}
// Se há erros, retornar null
if (!IsValid())
{
return null;
}
// Criar entidade com dados limpos
var nomeFormatado = StringExtensionMethods.ToTitleCase(command.Nome);
return new UsuarioEntity(nomeFormatado, emailLimpo, command.Idade);
}
public List<string> ObterErrosFormatados()
{
return Notifications.Select(n => $"{n.Property}: {n.Message}").ToList();
}
private bool IsValidEmail(string email)
{
return email.Contains("@") && email.Contains(".");
}
}
Exemplo 2: Processamento de Dados com Logging
public class ImportacaoService : NotifiableR
{
private readonly ILogger<ImportacaoService> _logger;
public ImportacaoService(ILogger<ImportacaoService> logger)
{
_logger = logger;
}
public async Task ProcessarArquivoAsync(List<string> linhas)
{
for (int i = 0; i < linhas.Count; i++)
{
var linha = linhas[i];
// Limpar dados
var dadosLimpos = linha.RemoveSpecialChars().TrimNotNull();
if (string.IsNullOrEmpty(dadosLimpos))
{
AddNotification("Linha", $"Linha {i + 1} está vazia ou inválida", aggregateId: i.ToString());
continue;
}
// Extrair números se necessário
var numeros = dadosLimpos.GetNumbers();
if (numeros.Length < 5)
{
AddNotification("Dados", $"Linha {i + 1} não possui dados suficientes", aggregateId: i.ToString());
}
}
// Log todas as notificações de uma vez
if (Notifications.Any())
{
var notificacoesComLog = LoggerNotifications(_logger, "ProcessarArquivo");
// Notificações são automaticamente logadas como Warning:
// "Validação em: ProcessarArquivo Linha Linha 1 está vazia ou inválida ..."
}
// Processar apenas linhas válidas
await ProcessarLinhasValidasAsync();
}
private async Task ProcessarLinhasValidasAsync()
{
// Lógica de processamento das linhas válidas
await Task.Delay(100); // Simular processamento
// Limpar notificações após processamento bem-sucedido
RemoveNotifications(removeAll: true);
}
}
Exemplo 3: Service com Multiple Validations
public class PedidoService : NotifiableR
{
public PedidoEntity ProcessarPedido(PedidoCommand command)
{
// Limpar dados de entrada
var clienteFormatado = command.Cliente?.TrimNotNull()?.ToTitleCase();
var observacoes = command.Observacoes?.RemoveSpecialChars();
// Validações básicas
ValidarDadosBasicos(clienteFormatado, command);
// Validações de itens
ValidarItens(command.Itens);
// Validações de enum
ValidarStatus(command.StatusTexto);
// Se há erros, retornar null
if (!IsValid())
{
return null;
}
// Criar entidade com dados processados
var pedido = new PedidoEntity(clienteFormatado, observacoes);
foreach (var item in command.Itens)
{
pedido.AdicionarItem(item.Produto.ToTitleCase(), item.Quantidade, item.Valor);
}
return pedido;
}
private void ValidarDadosBasicos(string cliente, PedidoCommand command)
{
if (string.IsNullOrEmpty(cliente))
{
AddNotification("Cliente", "Nome do cliente é obrigatório");
}
if (command.DataPedido == default)
{
AddNotification("DataPedido", "Data do pedido é obrigatória");
}
}
private void ValidarItens(List<ItemPedidoCommand> itens)
{
if (itens == null || !itens.Any())
{
AddNotification("Itens", "Pedido deve ter pelo menos um item");
return;
}
for (int i = 0; i < itens.Count; i++)
{
var item = itens[i];
if (string.IsNullOrEmpty(item.Produto?.TrimNotNull()))
{
AddNotification("Produto", $"Produto do item {i + 1} é obrigatório", aggregateId: i.ToString());
}
if (item.Quantidade <= 0)
{
AddNotification("Quantidade", $"Quantidade do item {i + 1} deve ser maior que zero", aggregateId: i.ToString());
}
if (item.Valor <= 0)
{
AddNotification("Valor", $"Valor do item {i + 1} deve ser maior que zero", aggregateId: i.ToString());
}
}
}
private void ValidarStatus(string statusTexto)
{
if (!string.IsNullOrEmpty(statusTexto))
{
bool isValidStatus = statusTexto.IsEnum<StatusPedido>(out int statusNumero);
if (!isValidStatus)
{
AddNotification("Status", $"Status '{statusTexto}' não é válido");
}
}
}
public void RemoverErrosEspecificos()
{
// Remover notificações de um campo específico
RemoveNotification("Cliente");
// Ou adicionar notificações de outro serviço
var outroServico = new ValidacaoService();
outroServico.ValidarRegrasNegocio();
AddNotifications(outroServico.Notifications);
}
}
API Reference
Core Extensions
AssemblyExtension
Métodos para obter informações do assembly da aplicação.
public static class AssemblyExtension
{
// Obtém o nome da aplicação
public static string GetApplicationNameByAssembly(this Assembly assembly);
// Obtém o número do build
public static string GetApplicationBuildNumber(this Assembly assembly);
// Obtém a versão da aplicação
public static string GetApplicationVersion(this Assembly assembly);
}
Exemplo de uso:
var assembly = Assembly.GetExecutingAssembly();
var appName = assembly.GetApplicationNameByAssembly();
var version = assembly.GetApplicationVersion();
var buildNumber = assembly.GetApplicationBuildNumber();
Console.WriteLine($"{appName} v{version} (Build: {buildNumber})");
StringExtensionMethods
Métodos de extensão para manipulação avançada de strings.
public static partial class StringExtensionMethods
{
// Remove caracteres especiais (mantém apenas ASCII 20-7E)
public static string RemoveSpecialChars(this string text);
// Mantém apenas letras e números
public static string GetLettersAndNumbersOnly(this string text);
// Obtém apenas caracteres Unicode
public static string GetUnicodeChars(this string text);
// Remove caracteres mas mantém diacríticos (acentos)
public static string RemoveCharsKeepDiacritics(this string text);
// Remove caracteres mas mantém os especificados
public static string RemoveCharsKeepChars(this string text, params string[] keepChars);
// Remove acentuação
public static string RemoveAccent(this string text);
// Extrai apenas números
public static string GetNumbers(this string text);
// Substring seguro (null-safe)
public static string SubstringNotNull(this string value, int start, int length);
// Converte para Title Case
public static string ToTitleCase(this string text);
// Remove \r\n e outros caracteres especificados
public static string GetReturnMessageWithoutRn(this string returnMessage, string otherCharToRemove = null);
}
Exemplo de uso:
string texto = "José & Maria - R$ 1.500,00!";
// Diferentes tipos de limpeza
string semEspeciais = texto.RemoveSpecialChars(); // "Jos Maria R 1500"
string apenasAlnum = texto.GetLettersAndNumbersOnly(); // "JosMaria1500"
string semAcentos = texto.RemoveAccent(); // "Jose & Maria - R$ 1.500,00!"
string apenasNumeros = texto.GetNumbers(); // "1500"
// Mantendo caracteres específicos
string comTracos = texto.RemoveCharsKeepChars("-", "$"); // "José Maria - R$ 150000"
// Title Case
string nome = "joão da silva".ToTitleCase(); // "João Da Silva"
StringExtensionToMethods
Métodos de conversão de string com proteção contra null.
public static partial class StringExtensionMethods
{
// ToUpper invariante seguro
public static string ToUpperInvariantNotNull(this string value);
// ToUpper seguro
public static string ToUpperNotNull(this string value);
// ToLower seguro
public static string ToLowerNotNull(this string value);
// ToLower invariante seguro
public static string ToLowerInvariantNotNull(this string value);
// Trim seguro
public static string TrimNotNull(this string value);
// ToString seguro
public static string ToStringNotNull(this string value);
}
Exemplo de uso:
string texto = null;
// Métodos tradicionais causariam NullReferenceException
// string upper = texto.ToUpper(); // ❌ Exception!
// Métodos seguros retornam null
string upper = texto.ToUpperNotNull(); // null
string lower = texto.ToLowerNotNull(); // null
string trimmed = texto.TrimNotNull(); // null
// Útil em chains
string resultado = input?.TrimNotNull()?.ToLowerNotNull();
EnumExtensionMethods
Métodos de extensão para trabalhar com enums.
public static class EnumExtensionMethods
{
// Obtém a descrição do enum (via [Description])
public static string GetDescription(this Enum GenericEnum);
// Converte string para número do enum
public static int ToEnumNumero<T>(this string value);
// Converte string para código do enum
public static string ToEnumCodigo<T>(this string value);
// Converte int para código do enum
public static string ToEnumCodigo<T>(this int value);
// Converte int para descrição do enum
public static string ToEnumDescricao<T>(this int value);
// Converte string para descrição do enum
public static string ToEnumDescricao<T>(this string value);
// Verifica se string é um enum válido
public static bool IsEnum<T>(this string value, out int enumCode);
// Obtém código do enum pela descrição
public static string GetCodeEnumByDescription<T>(this string value);
}
Exemplo de uso:
public enum StatusPedido
{
[Description("Aguardando Pagamento")]
AguardandoPagamento = 1,
[Description("Em Preparação")]
EmPreparacao = 2
}
// Obter descrição
var status = StatusPedido.AguardandoPagamento;
string descricao = status.GetDescription(); // "Aguardando Pagamento"
// Converter string para enum
int numero = "AguardandoPagamento".ToEnumNumero<StatusPedido>(); // 1
// Validar enum
bool isValid = "StatusInvalido".IsEnum<StatusPedido>(out int codigo);
// isValid = false, codigo = int.MaxValue
DateTimeExtensions
Métodos de extensão para DateTime e DateTimeOffset.
public static class DateTimeExtensions
{
// Formata para padrão REST (yyyy-MM-dd ou yyyy-MM-ddTHH:mm:ss)
public static string GetFormatRest(this DateTime dateTime, bool timeToo = false);
// Formata DateTimeOffset para padrão REST
public static string GetFormatRest(this DateTimeOffset dateTimeOffset);
// Obtém o primeiro dia útil do mês
public static DateTime GetFirstWorkingDay(this DateTime data);
// Obtém o primeiro dia útil do mês (DateTimeOffset)
public static DateTimeOffset GetFirstWorkingDay(this DateTimeOffset data);
}
Exemplo de uso:
var hoje = DateTime.Now;
// Formato REST
string dataRest = hoje.GetFormatRest(); // "2025-10-28"
string dataHoraRest = hoje.GetFormatRest(true); // "2025-10-28T14:30:00"
// Primeiro dia útil
var primeiroDiaUtil = hoje.GetFirstWorkingDay();
DictionaryExtension
Métodos de extensão para dicionários.
public static class DictionaryExtension
{
// Adiciona ou substitui valor no dicionário
public static void AddForce(this IDictionary<string, object> dictionary, string key, object value);
}
Exemplo de uso:
var dict = new Dictionary<string, object>
{
{ "nome", "João" }
};
// Adiciona ou atualiza sem verificar se existe
dict.AddForce("nome", "Maria"); // Substitui
dict.AddForce("idade", 30); // Adiciona
ObjectExtension
Métodos de extensão para objetos.
public static class ObjectExtension
{
// Compara objetos com proteção contra null
public static bool EqualsObjectNotNull(this object obj, object obj1);
}
Exemplo de uso:
object obj1 = null;
object obj2 = "teste";
// Comparação segura
bool iguais = obj1.EqualsObjectNotNull(obj2); // false (sem NullReferenceException)
Validation & Notification
NotifiableR
Classe base para implementação do Notification Pattern.
public class NotifiableR
{
// Propriedades
public IReadOnlyCollection<NotificationR> Notifications { get; }
// Métodos
public bool IsValid();
public void AddNotification(string property, string message, string aggregateId = null);
public void AddNotifications(IList<NotificationR> notifications);
public void RemoveNotification(string property);
public void RemoveNotifications(bool removeAll = true);
public IList<NotificationR> LoggerNotifications(ILogger logger, string logDescription);
}
Exemplo de uso:
public class ProdutoService : NotifiableR
{
public void ValidarProduto(string nome, decimal preco)
{
if (string.IsNullOrEmpty(nome))
AddNotification("Nome", "Nome é obrigatório");
if (preco <= 0)
AddNotification("Preco", "Preço deve ser maior que zero");
if (!IsValid())
{
// Processar erros
foreach (var error in Notifications)
Console.WriteLine($"{error.Property}: {error.Message}");
}
}
}
NotificationR
Estrutura de notificação individual.
public class NotificationR
{
public string Property { get; set; }
public string Message { get; set; }
public string AggregatorId { get; set; }
public DateTimeOffset DateOccurrence { get; set; }
}
DataAnnotationExtension
Extensões para integração com Data Annotations.
public static class DataAnnotationExtension
{
// Obtém notificações de validação
public static IList<NotificationR> GetNotifications(this IDataAnnotationCustom model);
// Valida modelo usando Data Annotations
public static bool DataAnnotationsIsValid(this IDataAnnotationCustom model);
}
Exemplo de uso:
public class ProdutoModel : IDataAnnotationCustom
{
[Required(ErrorMessage = "Nome é obrigatório")]
public string Nome { get; set; }
[Range(1, 99999, ErrorMessage = "Preço deve ser maior que zero")]
public decimal Preco { get; set; }
}
var produto = new ProdutoModel { Nome = "", Preco = 0 };
// Validar
bool isValid = produto.DataAnnotationsIsValid();
// Obter erros
var erros = produto.GetNotifications();
ValidatedNotNullExtensionMethods
Métodos para validação de null.
public static class ValidatedNotNullExtensionMethods
{
// Verifica se objeto não é null
public static bool NotNull<T>(this T value) where T : class;
// Verifica se coleção não é null ou vazia
public static bool NotNullOrZero<T>(this T value) where T : IEnumerable<object>;
// Verifica se enumerável não é null ou vazio
public static bool NotNullOrZero(this System.Collections.IEnumerable value);
}
Exemplo de uso:
string texto = "teste";
List<int> lista = new List<int> { 1, 2, 3 };
// Validações
bool textoValido = texto.NotNull(); // true
bool listaValida = lista.NotNullOrZero(); // true
string textoNulo = null;
bool nuloInvalido = textoNulo.NotNull(); // false
Advanced Extensions
ExpressionExtension
Métodos para manipulação de expressões LINQ.
public static class ExpressionExtension
{
// Combina expressões com operador AND ou OR
public static Expression<Func<T, bool>> CombineExpressions<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2,
bool useOrOperator = false);
}
Exemplo de uso:
Expression<Func<Produto, bool>> expr1 = p => p.Ativo;
Expression<Func<Produto, bool>> expr2 = p => p.Preco > 100;
// Combinar com AND
var combinadaAnd = expr1.CombineExpressions(expr2);
// Resultado: p => p.Ativo && p.Preco > 100
// Combinar com OR
var combinadaOr = expr1.CombineExpressions(expr2, useOrOperator: true);
// Resultado: p => p.Ativo || p.Preco > 100
// Usar em query
var produtos = dbContext.Produtos.Where(combinadaAnd).ToList();
ReflectionConstantsExtension
Métodos para obter constantes via reflexão.
public static class ReflectionConstantsExtension
{
// Obtém todas as constantes públicas de um tipo
public static IEnumerable<FieldInfo> GetPublicConstants(this Type type);
}
Exemplo de uso:
public static class StatusCodes
{
public const int OK = 200;
public const int NotFound = 404;
public const int ServerError = 500;
}
// Obter todas as constantes
var constantes = typeof(StatusCodes).GetPublicConstants();
foreach (var constante in constantes)
{
var nome = constante.Name;
var valor = constante.GetValue(null);
Console.WriteLine($"{nome} = {valor}");
}
// Output:
// OK = 200
// NotFound = 404
// ServerError = 500
DistinctExtension
Métodos para Distinct customizado.
public static class DistinctExtension
{
// Distinct usando propriedade específica
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source,
Func<TSource, object> keySelector);
}
Exemplo de uso:
var produtos = new List<Produto>
{
new Produto { Id = 1, Nome = "Produto A", Categoria = "Cat1" },
new Produto { Id = 2, Nome = "Produto B", Categoria = "Cat1" },
new Produto { Id = 3, Nome = "Produto C", Categoria = "Cat2" }
};
// Distinct por categoria
var categorias = produtos.Distinct(p => p.Categoria);
// Resultado: 2 produtos (Cat1 e Cat2)
JSON & Converters
JsonTypesExtensions
Métodos para conversão de tipos JSON.
public static class JsonTypesExtensions
{
// Converte tipo JSON customizado
public static object ConvertJsonTypeCustom(
this ref Utf8JsonReader reader,
Type propertyType);
}
Exemplo de uso:
// Usado internamente pelos conversores JSON customizados
// para converter tipos de forma inteligente durante deserialização
NullToDefaultValueConverter
Conversor JSON que transforma null em valores padrão.
public class NullToDefaultValueConverter<T> : JsonConverter<T>
where T : struct, IConvertible
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options);
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options);
}
Exemplo de uso:
var options = new JsonSerializerOptions
{
Converters = { new NullToDefaultValueConverter<int>() }
};
string json = "{\"idade\": null}";
var obj = JsonSerializer.Deserialize<Pessoa>(json, options);
// obj.Idade = 0 (valor padrão ao invés de exception)
JsonDateTimeConverters
Conversores para DateTime e DateTimeOffset.
// Converte DateTime para tipos inferidos
public class JsonDateTimeToInferredTypesConverter : JsonConverter<DateTime>
// Converte DateTimeOffset para tipos inferidos
public class JsonDateTimeOffsetToInferredTypesConverter : JsonConverter<DateTimeOffset>
// Converte objetos para tipos inferidos
public class JsonObjectToInferredTypesConverter : JsonConverter<object>
Exemplo de uso:
var options = new JsonSerializerOptions
{
Converters =
{
new JsonDateTimeToInferredTypesConverter(),
new JsonDateTimeOffsetToInferredTypesConverter()
}
};
// Deserialização inteligente de datas
string json = "{\"data\": \"2025-10-28T14:30:00\"}";
var obj = JsonSerializer.Deserialize<MyObject>(json, options);
Logging
NuuvifyLogFormatter
Formatador customizado de logs com cores.
public class NuuvifyLogFormatter : ConsoleFormatter
{
public NuuvifyLogFormatter(IOptionsMonitor<NuuvifyLogFormatterOptions> options);
public override void Write<TState>(
in LogEntry<TState> logEntry,
IExternalScopeProvider scopeProvider,
TextWriter textWriter);
}
NuuvifyLogSetupExtensions
Extensões para configuração de logging customizado.
public static class NuuvifyLogSetupExtensions
{
// Adiciona console formatter customizado
public static ILoggingBuilder AddNuuvifyConsoleFormatter(
this ILoggingBuilder builder,
Action<NuuvifyLogFormatterOptions> configure = null);
}
Exemplo de uso:
// Program.cs
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options =>
{
options.FormatterName = "nuuvify";
});
builder.Logging.AddNuuvifyConsoleFormatter(options =>
{
options.IncludeScopes = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
});
Helpers & Utilities
DomainEntity
Classe base para entidades de domínio.
public class DomainEntity
{
public string Id { get; protected set; }
public virtual DateTimeOffset DataCadastro { get; protected set; }
public virtual string UsuarioCadastro { get; set; }
public virtual DateTimeOffset? DataAlteracao { get; set; }
public virtual string UsuarioAlteracao { get; set; }
public override bool Equals(object obj);
public override int GetHashCode();
}
Exemplo de uso:
public class Produto : DomainEntity
{
public string Nome { get; private set; }
public decimal Preco { get; private set; }
public Produto(string nome, decimal preco)
{
// Id é gerado automaticamente
Nome = nome;
Preco = preco;
// DataCadastro é preenchido automaticamente
}
}
CustomGenericComparer
Comparador genérico customizado.
public class CustomGenericComparer<T> : IEqualityComparer<T>
{
public Func<T, object> KeySelector { get; set; }
public bool Equals(T x, T y);
public int GetHashCode(T obj);
}
Exemplo de uso:
var comparer = new CustomGenericComparer<Produto>
{
KeySelector = p => p.Nome
};
var lista = produtos.Distinct(comparer).ToList();
CacheTimeService
Serviço para gerenciamento de cache baseado em tempo.
public class CacheTimeService
{
// Implementação específica para cache temporal
}
PathHelper
Classe helper para manipulação e validação de caminhos de arquivos/diretórios com suporte cross-platform.
public static class PathHelper
{
// Sanitiza e normaliza um caminho de arquivo/diretório
public static string SanitizeAndNormalizePath(string rawPath);
// Verifica se um caminho existe (arquivo ou diretório)
public static bool PathExists(string path);
// Verifica se o caminho possui permissões de leitura e escrita
public static bool HasReadWriteAccess(string path);
}
Exemplo de uso:
using System.IO.Abstractions;
public class FileManagerService
{
public void ProcessarCaminhos()
{
// Normalizar caminhos com separadores misturados
string rawPath = @"C:\Users\Documents/MyApp\Data\\files/";
string normalized = PathHelper.SanitizeAndNormalizePath(rawPath);
// Windows: C:\Users\Documents\MyApp\Data\files
// Linux: C:/Users/Documents/MyApp/Data/files
// Caminhos UNC também são suportados
string uncPath = @"\\server\share\folder";
string normalizedUnc = PathHelper.SanitizeAndNormalizePath(uncPath);
// Resultado: \\server\share\folder
// Verificar se caminho existe
string dirPath = @"C:\Temp";
bool exists = PathHelper.PathExists(dirPath);
Console.WriteLine($"Caminho existe: {exists}");
// Verificar permissões de leitura/escrita (cross-platform)
bool hasAccess = PathHelper.HasReadWriteAccess(dirPath);
if (hasAccess)
{
Console.WriteLine("Diretório possui permissões de leitura/escrita");
// Processar arquivos no diretório
}
else
{
Console.WriteLine("Acesso negado ao diretório");
// Tratar erro de permissão
}
}
public void ValidarDiretoriosAntesDeProcessar(string[] diretorios)
{
foreach (var dir in diretorios)
{
// Sanitizar caminho primeiro
string dirNormalizado = PathHelper.SanitizeAndNormalizePath(dir);
// Verificar existência
if (!PathHelper.PathExists(dirNormalizado))
{
Console.WriteLine($"Diretório não existe: {dirNormalizado}");
continue;
}
// Verificar permissões
if (!PathHelper.HasReadWriteAccess(dirNormalizado))
{
Console.WriteLine($"Sem permissão de acesso: {dirNormalizado}");
continue;
}
// Processar diretório
ProcessarArquivos(dirNormalizado);
}
}
private void ProcessarArquivos(string diretorio)
{
// Lógica de processamento
var files = Directory.GetFiles(diretorio);
Console.WriteLine($"Processando {files.Length} arquivos em {diretorio}");
}
}
Características importantes:
- ✅ Cross-platform: Funciona em Windows, Linux e macOS
- ✅ Normalização de separadores: Converte
\e/para o separador correto da plataforma - ✅ Suporte a UNC paths: Preserva caminhos de rede
\\server\share - ✅ Verificação de permissões: Testa leitura/escrita criando arquivo temporário
- ✅ .NET Standard 2.1: Compatível com versões antigas do framework
- ✅ Tratamento de exceções: Captura erros de acesso, E/S e segurança
Observações sobre HasReadWriteAccess():
- Cria um arquivo temporário com nome único (GUID) no diretório
- Tenta escrever conteúdo no arquivo
- Deleta o arquivo de teste
- Se qualquer operação falhar, retorna
false - Captura exceções:
UnauthorizedAccessException,IOException,SecurityException, etc.
Constants
Constantes do sistema.
public static class Constants
{
// Header de correlação
public static string CorrelationHeader { get; }
// Header de claim do usuário
public static string UserClaimHeader { get; }
// Header de validação do usuário
public static string UserIsValidToApplication { get; }
}
Exemplo de uso:
// Em um middleware ou controller
var correlationId = HttpContext.Request.Headers[Constants.CorrelationHeader];
var userClaim = HttpContext.Request.Headers[Constants.UserClaimHeader];
FileData
Classe para manipulação de dados de arquivo.
public class FileData
{
// Propriedades e métodos para manipulação de arquivos
}
WebProxyConfigureMethod
Configuração de proxy web.
public class WebProxyConfigureMethod
{
// Métodos para configurar proxy HTTP
}
Interfaces
IDataAnnotationCustom
Interface para modelos com validação via Data Annotations.
public interface IDataAnnotationCustom
{
// Implementar para habilitar extensões de validação
}
INotPersistingAsTable
Marca uma entidade que não deve ser persistida como tabela.
public interface INotPersistingAsTable
{
// Interface de marcação (marker interface)
}
IRepositoryValidation
Interface para validações em repositórios.
public interface IRepositoryValidation
{
// Métodos de validação customizados para repositórios
}
Métodos Legados (Notification Pattern)
NotifiableR (Continuação)
IReadOnlyCollection<NotificationR> Notifications: Lista de notificaçõesbool IsValid(): Verifica se não há notificaçõesvoid AddNotification(string property, string message, string aggregateId = null): Adiciona notificaçãovoid AddNotifications(IList<NotificationR> notifications): Adiciona múltiplas notificaçõesvoid RemoveNotification(string property): Remove notificações de uma propriedadevoid RemoveNotifications(bool removeAll = true): Remove todas as notificaçõesIList<NotificationR> LoggerNotifications(ILogger logger, string logDescription): Log automático das notificações
NotificationR (Continuação)
string Property: Nome da propriedadestring Message: Mensagem de errostring AggregatorId: ID do agregadoDateTimeOffset DateOccurrence: Data/hora da notificação
String Extensions (Continuação)
StringExtensionMethods (Continuação)
string RemoveSpecialChars(this string text): Remove caracteres especiais ASCIIstring GetLettersAndNumbersOnly(this string text): Mantém apenas letras e númerosstring GetNumbers(this string text): Extrai apenas númerosstring RemoveAccent(this string text): Remove acentosstring ToTitleCase(this string text): Converte para Title Casestring ToUpperNotNull(this string value): ToUpper seguro (null-safe)string ToLowerNotNull(this string value): ToLower segurostring TrimNotNull(this string value): Trim seguro
Enum Extensions (Continuação)
EnumExtensionMethods (Continuação)
string GetDescription(this Enum GenericEnum): Obtém descrição do enumint ToEnumNumero<T>(this string value): Converte string para número do enumstring ToEnumTexto<T>(this int numero): Converte número para texto do enumbool IsEnum<T>(this string value, out int result): Verifica se string é enum válido
Domain Entity (Continuação)
DomainEntity (Continuação)
string Id: Identificador único (GUID)DateTimeOffset DataCadastro: Data de cadastrostring UsuarioCadastro: Usuário que cadastrouDateTimeOffset? DataAlteracao: Data da última alteraçãostring UsuarioAlteracao: Usuário que alterouoverride bool Equals(object obj): Comparação por Idoverride int GetHashCode(): Hash baseado no tipo e Id
JSON Extensions (Continuação)
NullToDefaultValueConverter (Continuação)
- Converte valores null para valores padrão durante serialização JSON
Troubleshooting
Problemas Comuns
NullReferenceException com Strings
Problema: Erro ao chamar métodos em strings nulas
Solução: Usar extensões null-safe
// ❌ Incorreto
string texto = null;
string upper = texto.ToUpper(); // NullReferenceException
// ✅ Correto
string upper = texto.ToUpperNotNull(); // Retorna null
Notificações não aparecendo
Problema: Notificações adicionadas mas não aparecem
Causa: Verificar se está herdando de NotifiableR
Solução: Herdar corretamente da classe base
// ✅ Correto
public class MeuService : NotifiableR
{
public void MinhaValidacao()
{
AddNotification("Campo", "Mensagem");
bool temErros = !IsValid(); // Funciona corretamente
}
}
Enum conversions falhando
Problema: ToEnumNumero() retorna int.MaxValue
Causa: String não corresponde a um valor válido do enum
Solução: Verificar se o valor existe no enum
public enum MeuEnum { Valor1 = 1, Valor2 = 2 }
// ✅ Verificar antes de converter
string valorTexto = "Valor1";
if (valorTexto.IsEnum<MeuEnum>(out int numero))
{
// Conversão foi bem-sucedida
Console.WriteLine($"Número: {numero}");
}
Logs e Debugging
Para debugging das notificações:
public class DebugService : NotifiableR
{
private readonly ILogger<DebugService> _logger;
public void DebugarNotificacoes()
{
AddNotification("Campo1", "Erro 1");
AddNotification("Campo2", "Erro 2");
// Debug manual
foreach (var notification in Notifications)
{
Console.WriteLine($"[{notification.DateOccurrence}] {notification.Property}: {notification.Message}");
}
// Log automático com detalhes
LoggerNotifications(_logger, "DebugService.DebugarNotificacoes");
}
}
Changelog
Ver arquivo CHANGELOG.md para histórico detalhado de alterações.
📞 Suporte
Para dúvidas, issues ou contribuições:
- 🐛 Issues: GitHub Issues
- 📧 Email: suporte@zocate.li
- 📖 Documentação: Wiki do Projeto
Nuuvify CommonPack - Construindo soluções robustas para .NET 🚀
| 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 | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | 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.1
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.Logging (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Logging.Configuration (>= 8.0.1)
- Microsoft.Extensions.Logging.Console (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Diagnostics.DiagnosticSource (>= 8.0.1)
- System.Runtime.Extensions (>= 4.3.1)
- System.Security.AccessControl (>= 6.0.1)
- System.Security.Principal.Windows (>= 5.0.0)
- System.Text.Json (>= 8.0.5)
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0-test.25052502 | 0 | 5/25/2025 |
| 3.0.0-test.25050204 | 0 | 5/2/2025 |
| 3.0.0-test.25042801 | 0 | 4/28/2025 |
| 3.0.0-test.25042712 | 0 | 4/28/2025 |
| 3.0.0-test.25042711 | 0 | 4/28/2025 |
| 3.0.0-test.25042709 | 0 | 4/28/2025 |
| 3.0.0-test.25042708 | 0 | 4/28/2025 |
| 3.0.0-test.25042707 | 0 | 4/28/2025 |
| 3.0.0-test.25042705 | 0 | 4/28/2025 |
| 3.0.0-test.25042703 | 0 | 4/28/2025 |
| 3.0.0-test.25042701 | 0 | 4/27/2025 |
| 3.0.0-test.25041702 | 4 | 4/17/2025 |
| 2.2.0-test.25102902 | 0 | 10/29/2025 |
| 2.1.0-test.25101302 | 162 | 10/13/2025 |
| 2.1.0-test.25101102 | 4 | 10/12/2025 |
| 2.1.0-test.25100702 | 5 | 10/8/2025 |
| 2.1.0-test.25100602 | 16 | 10/6/2025 |
| 2.1.0-test.25100507 | 5 | 10/6/2025 |
| 2.1.0-test.25100503 | 3 | 10/5/2025 |
| 2.1.0-test.25093008 | 31 | 9/30/2025 |
| 2.0.0-preview.25041508 | 0 | 4/16/2025 |
| 2.0.0-preview.25041506 | 44 | 4/16/2025 |