using FluentValidation; using FluentValidation.Results; using Microsoft.Extensions.Options; namespace Vegasco.Server.Api.Common; public static class ValidatorExtensions { /// /// Asynchronously validates an instance of against all instances in . /// /// /// /// /// The failed validation results. public static async Task> ValidateAllAsync(this IEnumerable> validators, T instance, CancellationToken cancellationToken = default) { List> validationTasks = validators .Select(validator => validator.ValidateAsync(instance, cancellationToken)) .ToList(); await Task.WhenAll(validationTasks); List failedValidations = validationTasks .Select(x => x.Result) .Where(x => !x.IsValid) .ToList(); return failedValidations; } public static Dictionary ToCombinedDictionary(this IEnumerable validationResults) { // Use a hash set to avoid duplicate error messages. Dictionary> combinedErrors = []; foreach (ValidationFailure? error in validationResults.SelectMany(x => x.Errors)) { if (!combinedErrors.TryGetValue(error.PropertyName, out HashSet? value)) { value = [error.ErrorMessage]; combinedErrors[error.PropertyName] = value; continue; } value.Add(error.ErrorMessage); } return combinedErrors.ToDictionary(x => x.Key, x => x.Value.ToArray()); } public static OptionsBuilder ValidateFluently(this OptionsBuilder builder) where T : class { builder.Services.AddTransient>(serviceProvider => { IEnumerable> validators = serviceProvider.GetServices>() ?? []; return new FluentValidationOptions(builder.Name, validators); }); return builder; } }