From 9c9762b4ecbd816be98ee0dd606fe15cc253b415 Mon Sep 17 00:00:00 2001 From: 杨宇千 Date: Tue, 22 Oct 2019 20:49:52 +0800 Subject: ... --- Timeline/Models/Validation/UsernameValidator.cs | 37 +++++++--------- Timeline/Models/Validation/Validator.cs | 58 +++++++++++++------------ 2 files changed, 45 insertions(+), 50 deletions(-) (limited to 'Timeline/Models') diff --git a/Timeline/Models/Validation/UsernameValidator.cs b/Timeline/Models/Validation/UsernameValidator.cs index ecc3b5b3..65d4da71 100644 --- a/Timeline/Models/Validation/UsernameValidator.cs +++ b/Timeline/Models/Validation/UsernameValidator.cs @@ -1,46 +1,39 @@ -using Microsoft.Extensions.Localization; -using System.Linq; -using System.Text.RegularExpressions; +using System.Linq; namespace Timeline.Models.Validation { public class UsernameValidator : Validator { public const int MaxLength = 26; - public const string RegexPattern = @"^[a-zA-Z0-9_][a-zA-Z0-9-_]*$"; - private readonly Regex _regex = new Regex(RegexPattern); - - protected override bool DoValidate(string value, IStringLocalizerFactory localizerFactory, out string message) + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "Already checked in base class.")] + protected override (bool, ValidationMessageGenerator) DoValidate(string value) { if (value.Length == 0) { - message = "An empty string is not permitted."; - return false; + return (false, factory => + factory?.Create(typeof(UsernameValidator))?["ValidationMessageEmptyString"] + ?? Resources.Models.Validation.UsernameValidator.InvariantValidationMessageEmptyString); } if (value.Length > 26) { - message = $"Too long, more than 26 characters is not premitted, found {value.Length}."; - return false; + return (false, factory => + factory?.Create(typeof(UsernameValidator))?["ValidationMessageTooLong"] + ?? Resources.Models.Validation.UsernameValidator.InvariantValidationMessageTooLong); } foreach ((char c, int i) in value.Select((c, i) => (c, i))) - if (char.IsWhiteSpace(c)) + { + if (!(char.IsLetterOrDigit(c) || c == '-' || c == '_')) { - message = $"A whitespace is found at {i} . Whitespace is not permited."; - return false; + return (false, factory => + factory?.Create(typeof(UsernameValidator))?["ValidationMessageInvalidChar"] + ?? Resources.Models.Validation.UsernameValidator.InvariantValidationMessageInvalidChar); } - - var match = _regex.Match(value); - if (!match.Success) - { - message = "Regex match failed."; - return false; } - message = ValidationConstants.SuccessMessage; - return true; + return (true, SuccessMessageGenerator); } } } diff --git a/Timeline/Models/Validation/Validator.cs b/Timeline/Models/Validation/Validator.cs index a3800b71..606ba7b4 100644 --- a/Timeline/Models/Validation/Validator.cs +++ b/Timeline/Models/Validation/Validator.cs @@ -6,9 +6,16 @@ using Timeline.Helpers; namespace Timeline.Models.Validation { + /// + /// Generate a message from a localizer factory. + /// If localizerFactory is null, it should return a neutral-cultural message. + /// + /// The localizer factory. Could be null. + /// The message. + public delegate string ValidationMessageGenerator(IStringLocalizerFactory? localizerFactory); + /// /// A validator to validate value. - /// See . /// public interface IValidator { @@ -16,14 +23,8 @@ namespace Timeline.Models.Validation /// Validate given value. /// /// The value to validate. - /// The validation message. - /// True if validation passed. Otherwise false. - bool Validate(object? value, IStringLocalizerFactory localizerFactory, out string message); - } - - public static class ValidationConstants - { - public const string SuccessMessage = "Validation succeeded."; + /// Validation success or not and the message generator. + (bool, ValidationMessageGenerator) Validate(object? value); } /// @@ -39,36 +40,32 @@ namespace Timeline.Models.Validation /// public abstract class Validator : IValidator { - [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "")] - public bool Validate(object? value, IStringLocalizerFactory localizerFactory, out string message) + public (bool, ValidationMessageGenerator) Validate(object? value) { if (value == null) { - var localizer = localizerFactory.Create("Models.Validation.Validator"); - message = localizer["ValidatorMessageNull"]; - return false; + return (false, factory => + factory?.Create("Models.Validation.Validator")?["ValidatorMessageNull"] + ?? Resources.Models.Validation.Validator.InvariantValidatorMessageNull + ); } if (value is T v) { - return DoValidate(v, localizerFactory, out message); + return DoValidate(v); } else { - var localizer = localizerFactory.Create("Models.Validation.Validator"); - message = localizer["ValidatorMessageBadType", typeof(T).FullName]; - return false; + return (false, factory => + factory?.Create("Models.Validation.Validator")?["ValidatorMessageBadType", typeof(T).FullName] + ?? Resources.Models.Validation.Validator.InvariantValidatorMessageBadType); } } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods")] - protected static string GetSuccessMessage(IStringLocalizerFactory factory) - { - var localizer = factory.Create("Models.Validation.Validator"); - return localizer["ValidatorMessageSuccess"]; - } + protected static ValidationMessageGenerator SuccessMessageGenerator { get; } = factory => + factory?.Create("Models.Validation.Validator")?["ValidatorMessageSuccess"] ?? Resources.Models.Validation.Validator.InvariantValidatorMessageSuccess; - protected abstract bool DoValidate(T value, IStringLocalizerFactory localizerFactory, out string message); + protected abstract (bool, ValidationMessageGenerator) DoValidate(T value); } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, @@ -113,11 +110,16 @@ namespace Timeline.Models.Validation protected override ValidationResult IsValid(object value, ValidationContext validationContext) { - var localizerFactory = validationContext.GetRequiredService(); - if (_validator.Validate(value, localizerFactory, out var message)) + var (result, messageGenerator) = _validator.Validate(value); + if (result) + { return ValidationResult.Success; + } else - return new ValidationResult(message); + { + var localizerFactory = validationContext.GetRequiredService(); + return new ValidationResult(messageGenerator(localizerFactory)); + } } } } -- cgit v1.2.3