What are the best practices for implementing DryIoc, FluentValidation and Lazy?

12

I'm building an architecture based on the use of Lazy, DryIoc e o FluentValidation .

I intend to do all validations with the object. When I actually use the object I will instantiate it (Start). I do not know if I'm sinning in any detail by using Lazy and DryIoc , I did not find an example of how to implement them in the same solution.

I would appreciate it if someone opened my eyes to some blind spot that I let pass, or to let me know how to do it correctly.

Input.

    using DryIoc;
    using FluentValidation;
    using System;
    using System.Linq;
    using TesteDryIoC.Generic.Validacoes;

    namespace TesteDryIoC.Generic
    {
    class Program
    {
        static void Main(string[] args)
        {
            var container = ContainerRegister.getContainer();

            // buscar a validador especifico por propriedade
            var validadorPropriedade = ProvadersValidator<Cliente>.GetValidators(container, (validadores) =>
            {
                var validadorEncontrado = validadores.FirstOrDefault(x => x.CreateDescriptor().GetRulesForMember("Observacao").Any());
                return validadorEncontrado ?? validadores.First();
            });

            var validadorRule = ProvadersValidator<Cliente>.GetValidators(container, (validadores) =>
            {
                var validadorEncontrado = validadores.FirstOrDefault(x => x. CreateDescriptor().GetValidatorsForMember("ClienteValidatorRuleSet").Any());
                return validadorEncontrado ?? validadores.First();
            });


            Console.WriteLine("cliente1");
            Cliente cliente = new Cliente();
            cliente.Nome = "Marconcilio";
            cliente.SobreNome = "Souza";
            cliente.Observacao = "teste";
            cliente.Email = "[email protected]";
            cliente.Idade = 32;
            cliente.DtInclusao = DateTime.Now;
            cliente.Ativo = true;
            cliente.Senha = "";

            var resultad = validadorPropriedade.Validate(cliente);

            foreach (var item in resultad.Errors)
            {
                Console.WriteLine(item.ErrorMessage);
            }
            Console.ReadKey();
            }
        }
    }

Client Class

  using FluentValidation.Results;
  using System;

  namespace TesteDryIoC.Generic {
   public class Cliente {
    public string Nome {
     get;
     set;
    }
    public string SobreNome {
     get;
     set;
    }
    public string Email {
     get;
     set;
    }
    public int Idade {
     get;
     set;
    }
    public string Observacao {
     get;
     set;
    }
    public DateTime DtInclusao {
     get;
     set;
    }
    public bool Ativo {
     get;
     set;
    }
    public string Senha {
     get;
     set;
    }
   }
  }

Container Register

using DryIoc;
using FluentValidation;
using System.Linq;
using System.Reflection;

namespace TesteDryIoC.Generic {
 public static class ContainerRegister {
  public static Container getContainer() {
   Container container = new Container();

   var implementingClasses =
    Assembly.GetExecutingAssembly()
    .GetTypes().Where(type =>
     type.ImplementsServiceType(typeof(IValidator))
    );

   foreach(var implementingClass in implementingClasses) {
    var interfaceValidator = implementingClass.GetImplementedInterfaces()[0];
    container.Register(interfaceValidator, implementingClass);
   }

   return container;
  }
 }
}

Provaders Validator

using DryIoc;
using FluentValidation;
using System;
using System.Collections.Generic;
using System.Linq;

namespace TesteDryIoC.Generic {
 public static class ProvadersValidator < T1 > where T1: class {
  public static IValidator GetValidators(Container container, Func < IEnumerable < IValidator < T1 >> , IValidator < T1 >> criterio = null) {
   var validador = container.Resolve < Lazy < IEnumerable < IValidator < T1 >>> > ();
   var validadores = validador.Value;
   // TODO: função para selecionar qual usar
   if (criterio != null)
    return criterio(validadores);

   return validadores.First();
  }
 }
}

Validation class

using FluentValidation;
using System;

namespace TesteDryIoC.Generic.Validacoes {
 public class ClienteValidator: AbstractValidator < Cliente > {
  public ClienteValidator() {
   RuleFor(x => x.Nome)
    // Garante que a propriedade especificada não seja nula                            
    .NotNull().WithMessage("{PropertyName} deve ser preenchido")
    //  Garante que a propriedade especificada não seja nula, uma string vazia ou espaço em branco (ou o valor padrão para tipos de valor, por exemplo, 0 para int
    .NotEmpty().WithMessage("{PropertyName} não pode estar em branco")
    // Especificar o tamanho minimo para o nome
    .MinimumLength(2).WithMessage("{PropertyName} não pode ter menos que 2 caracteres")
    // especificar o tamanho máximo para o nome
    .MaximumLength(200).WithMessage("{PropertyName} não pode ser maior que 200")
    // Garante que o valor da propriedade especificada não seja igual a um valor específico 
    .NotEqual("Carlos").WithMessage("{PropertyName} não pode igual a Carlos")
    //(ou não igual ao valor de outra propriedade)
    .NotEqual(c => c.SobreNome).WithMessage("{PropertyName} não pode igual ao sobrenome");

   RuleFor(x => x.Idade)
    .NotNull()
    .NotEmpty()
    // Garante que o valor da propriedade especificada seja maior do que um valor específico(ou maior que o valor de outra propriedade)
    .GreaterThan(18).WithMessage("{PropertyName} Minima é 18 anos!");

   // Garante que o comprimento de uma propriedade de string específica esteja dentro do intervalo especificado.
   RuleFor(x => x.Observacao)
    .Length(10, 250)
    .WithMessage("{PropertyName} tem que ter entre 10 e 250 caracteres");

   // Garante que o valor da propriedade especificada seja um formato de endereço de e-mail válido.
   RuleFor(x => x.Email)
    .EmailAddress().WithMessage("{ PropertyName} é inválido");

   //  Passa o valor da propriedade especificada para um delegate personalizado que pode executar a lógica de validação personalizada no valor
   RuleFor(x => x.DtInclusao).Must(ClienteValidatorDate).WithMessage("{ PropertyName} é inválido");

   //  Garante que o valor da propriedade especificada corresponda à expressão regular dada
   RuleFor(x => x.Senha)
    .Matches("").WithMessage("{ PropertyName} é inválido");

  }

  private bool ClienteValidatorDate(DateTime date) {
   if (date ==
    default (DateTime))
    return false;
   return true;
  }
  private bool ClienteValidatorDate(DateTime ? date) {
   if (date ==
    default (DateTime))
    return false;
   return true;
  }
 }
}
  • How could I make my class ProvadersValidator to return a generic type instead of IValidator return the type that is being filtered in ( container ) if ClienteValidator ?
asked by anonymous 03.07.2017 / 16:14

1 answer

1

I think I understood your doubt, to do what you want you would just let the following classes change:

Program:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("cliente1");
        var cliente = new Cliente {
            Nome = "Marconcilio",
            SobreNome = "Souza",
            Observacao = "teste",
            Email = "[email protected]",
            Idade = 32,
            DtInclusao = DateTime.Now,
            Ativo = true,
            Senha = ""
        };

        // Validando com qualquer validador, pega o primeiro disponível e retorna uma exception se não houver validador registrado.
        var validandoComQualquerValidador = ProvadersValidator<Cliente>.Validate(cliente);
        // Validando com validador localizado propropriedade.
        var validandoComValidadorLocalizadoPorPropriedade = ProvadersValidator<Cliente>.Validate(cliente, x => 
            x.CreateDescriptor().GetRulesForMember("Observacao").Any());
        // Validando com validador localizado por rule.
        var validandoComValidadorLocalizadoPorRule = ProvadersValidator<Cliente>.Validate(cliente, x =>
            x.CreateDescriptor().GetValidatorsForMember("ClienteValidatorRuleSet").Any());

        foreach (var item in validandoComQualquerValidador.Errors)
            Console.WriteLine(item.ErrorMessage);

        foreach (var item in validandoComValidadorLocalizadoPorPropriedade.Errors)
            Console.WriteLine(item.ErrorMessage);

        foreach (var item in validandoComValidadorLocalizadoPorRule.Errors)
            Console.WriteLine(item.ErrorMessage);

        Console.ReadKey();
    }
}

ProvadersValidator:

public static class ProvadersValidator
{
    public static IValidator GetValidator<T>(Func<IValidator, bool> clause = null)
    {
        var container = ContainerRegister.GetContainer();
        var validators = container.Resolve<Lazy<IEnumerable<IValidator<T>>>>().Value;

        if (validators == null || !validators.Any())
            throw new Exception(
                $"Não foram localizados validadores para a classe {typeof(T).FullName}"
            );

        if (clause == null) return validators.First();

        var filtered = validators.Where(clause);

        return filtered.Any() ? filtered.First() : validators.First();
    }

    public static ValidationResult Validate<T>(T target)
    {
        var validator = GetValidator<T>();
        var result = validator.Validate(target);
        return result;
    }

    public static ValidationResult Validate<T>(T target, Func<IValidator, bool> clause)
    {
        var validator = GetValidator<T>(clause);
        var result = validator.Validate(target);
        return result;
    }
}

PS: It was not necessary to intervene in the other classes ...

    
27.07.2017 / 19:51