using static System.Console;
using System.Collections.Generic;
public string Nome { get; set; } = "";
public string Endereco { get; set; } = "";
public int Idade { get; set; } = 0;
public string Cargo { get; set; } = "";
public decimal Salario { get; set; } = 0M;
public class ModelPessoa : Model<Pessoa> {
override public bool Validate() {
Required("Nome", Value.Nome);
Required("Cargo", Value.Cargo);
Custom("Salário", "SalarioValido", "O Salário não atende os requisitos", ValidaSalario);
Range("Idade", Value.Idade, Util.GetMaioridade(), 120);
return (IsValid = Errors.Count == 0);
public int AsIdade(string texto) {
if (int.TryParse(texto, out idade)) {
Errors["IdadeInconsistente"] = new Invalidation("Idade", "A Idade foi digitada de forma inconsistente");
public decimal AsSalario(string texto) {
if (decimal.TryParse(texto, out salario)) {
Errors["SalarioInconsistente"] = new Invalidation("Salario", "O Salário foi digitado de forma inconsistente");
private void ValidaEndereco() {
if (!Util.IsStandardAddress(Value.Endereco)) {
AddError("EnderecoPadrao", "Endereço", "EnderecoPadrao", "O Endereço está em formato inválido.");
private bool ValidaSalario(object[] values) {
return ((!Errors.ContainsKey("IdadeInconsistente") && Value.Idade > 21 && Value.Salario > 1000M)) ||
(Value.Cargo != "Gerente" && Value.Salario > 900M) ||
(Value.Cargo == "Gerente" && Value.Salario > 1200M);
public static class Util {
public static string Read(string label) {
public static int GetMaioridade() => 18;
public static bool IsStandardAddress(string address) => address.Length > 2 && (address.Substring(0, 3) == "Rua" || address.Substring(0, 3) == "Av.");
public static void Main(string[] args) {
var mp = new ModelPessoa();
mp.Messages["Idade"] = "A pessoa precisa ser maior de idade";
mp.Value.Nome = Util.Read("Nome: ");
mp.Value.Endereco = Util.Read("Endereço: ");
mp.Value.Idade = mp.AsIdade(Util.Read("Idade: "));
mp.Value.Cargo = Util.Read("Cargo: ");
mp.Value.Salario = mp.AsSalario(Util.Read("Salário: "));
Pessoa funcionario = mp.Value;
WriteLine("Cadastro efetuado!");
WriteLine("Erros ocorreram!");
foreach(var erro in mp.Errors) {
public class Invalidation {
public string Data { get; private set; }
get => message ?? "Dado inválido";
public Invalidation(string data, string message = null) {
public override string ToString() => Message;
public abstract class Model<T> where T : new() {
public T Value { get; private set; } = new T();
public bool IsValid { get; protected set; } = false;
public Dictionary<string, Invalidation> Errors { get; protected set; } = new Dictionary<string, Invalidation>();
public Dictionary<string, string> Messages { get; set; } = new Dictionary<string, string>();
public abstract bool Validate();
protected void Required(string field, string value) {
if (string.IsNullOrEmpty(value)) AddError(field + "Required", field, "Required", "O campo {0} é obrigatório.");
protected void Range(string field, int value, int min, int max) {
if (value < min || value > max) AddError(field + "Range", field, "Range", "O campo {0} deve estar na faixa de {1} até {2}.", min, max);
protected void Custom(string field, string messageKey, string messageAlt, Func<object[], bool> condition, params object[] values) {
if (!condition(values)) {
if (values != null && values.Length > 0) {
AddError(field + messageKey, field, messageKey, messageAlt, values?[0], values?[1], values?[2]);
AddError(field + messageKey, field, messageKey, messageAlt);
protected void AddError(string errorKey, string field, string messageKey, string defaultMessage, object value1 = null, object value2 = null, object value3 = null) {
Errors[errorKey] = new Invalidation(field, string.Format(Messages.TryGetValue(messageKey, out message) ? message : defaultMessage, field, value1, value2, value3));