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
- 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();
- 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ę