Nowoczene podejście do walidacji

0

cześć
znalażlem taki oto wpis gdzieś w sieci
https://mentormate.com/bg/blog/modern-validation-patterns-in-c-sharp/

i chciałem zrobić dzialający przykład
wyszło mi mniej więcej coś takiego:

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Validator
{

    public class ValidationResult
    {
        public bool Success { get; private set; }
        public bool HasErrors => ErrorType != null;
        public ErrorType ErrorType { get; private set; }
        public static ValidationResult CreateSuccess()
        {
            var vr = new ValidationResult {Success = true};
            return vr;
        }

        public static ValidationResult CreateWithError(ErrorType errorType)
        {
            var vr = new ValidationResult { Success = false, ErrorType  = errorType};
            return vr;
        }
    }

    public class ErrorType
    {
        public int Code { get; }
        public int Type { get; }
        public string Description { get; }

        public ErrorType(int code, int type, string description)
        {
            Code = code;
            Type = type;
            Description = description;
        }
    }

    public interface IValidationRule
    {
        ValidationResult Error { get; }
        bool Validate();

    }

    public interface IValidationRule<T>
    {
        ValidationResult Error { get; }
        bool Validate(T arg);
    }

    public class ValidationRule<TValidator, TSubject> : IValidationRule
        where TValidator : IValidationRule<TSubject>, new()
    {
        private readonly TValidator _validator = new TValidator();
        private readonly TSubject _validationSubject;
        public ValidationResult Error => _validator.Error;

        public ValidationRule(TSubject validationSubject)
        {
            _validationSubject = validationSubject;
        }

        public bool Validate() => _validator.Validate(_validationSubject);

    }

    public class NameShouldNotBeEmpty : IValidationRule<string>
    {
        public ValidationResult Error => ValidationResult.CreateWithError(new ErrorType(1,2, "msg"));
        public bool Validate(string name) => !string.IsNullOrWhiteSpace(name);

    }
    public class NameHasOnlyLetters : IValidationRule<string>
    {
        public ValidationResult Error => ValidationResult.CreateWithError(new ErrorType(2, 2, "msg"));
        public bool Validate(string name) => !Regex.Match(name, "^[0-9]+$").Success;

    }

    public class Validator
    {
        private readonly List<IValidationRule> _rules = new List<IValidationRule>();

        public Validator AddRule<TValidator, TSubject>(TSubject validationSubject)
            where TValidator : IValidationRule<TSubject>, new()
        {
            var validationRule = new ValidationRule<TValidator, TSubject>(validationSubject);

            _rules.Add(validationRule);

            return this;
        }
        public ValidationResult Validate()
        {
            foreach (var rule in _rules)
            {
                if (!rule.Validate())
                {
                    return rule.Error;
                }
            }

            return ValidationResult.CreateSuccess();
        }

        public static void Main(string [] args)
        {
            var validator = new Validator();
            validator
                .AddRule<NameShouldNotBeEmpty, string>("ala")
                .AddRule<NameHasOnlyLetters, string>("ala")
                .Validate();
        }
    }
   
}

Mam do szanownych takie pytanie

  1. czy dalo by się jakoś zrobić żeby nie trzeba bylo podawać drugiego parametru w AddRule - tylko klase do walidacji
 var validator = new Validator();
            validator
                .AddRule<NameShouldNotBeEmpty>("ala")
                .AddRule<NameHasOnlyLetters>("ala")
                .Validate();
  1. jak zrobić gdy mamy walidację stopniową
    np
    coś może mieć trzy stany - taki enum
    istnieje, nieistnieje, brak_identyfikacji
    i np
  • brak_identyfikacji - powoduje zatrzymanie procesu, bo w żądaniu nie przesłano czegoś co pozwala swtierdzić czy ISTENIEJE czy NIE
  • jak nie istnieje - proces jest kontynuowany
  • jak istnieje - sparawdzane są dodatkowe regóły spójności

myślałem żeby to zrobić tak

 var validator2 = new Validator().AddRule<CheckFirstElem>(elem1).AddRule<CheckSecondElem>(elem2).Validate();

 var validator = new Validator();
            validator
                .AddRule<CheckIfIsProperDefined>(param)
                .AddValidation(validator2)
                .Validate();

ale taki układ w cale nie wymusza kolejnosci mogę dodać walidator przed rule

jak ktoś ma na to pomysł i jest skłonny się podzielić z góry dziękuję

3

Spójrz jak to zrobili tutaj: https://fluentvalidation.net/

1 użytkowników online, w tym zalogowanych: 0, gości: 1