using FluentValidation; using FluentValidation.Results; using FluentValidation.Validators; namespace Recyclarr.Common.FluentValidation; public static class FluentValidationExtensions { // From: https://github.com/FluentValidation/FluentValidation/issues/1648 // ReSharper disable once UnusedMethodReturnValue.Global public static IRuleBuilderOptions SetNonNullableValidator( this IRuleBuilder ruleBuilder, IValidator validator, params string[] ruleSets) { var adapter = new NullableChildValidatorAdaptor(validator, validator.GetType()) { RuleSets = ruleSets }; return ruleBuilder.SetAsyncValidator(adapter); } private sealed class NullableChildValidatorAdaptor : ChildValidatorAdaptor, IPropertyValidator, IAsyncPropertyValidator { public NullableChildValidatorAdaptor(IValidator validator, Type validatorType) : base(validator, validatorType) { } public override bool IsValid(ValidationContext context, TProperty? value) { return base.IsValid(context, value!); } public override Task IsValidAsync( ValidationContext context, TProperty? value, CancellationToken cancellation) { return base.IsValidAsync(context, value!, cancellation); } } public static IEnumerable IsValid( this IEnumerable source, TValidator validator, Action, TSource>? handleInvalid = null) where TValidator : IValidator { foreach (var s in source) { var result = validator.Validate(s); if (result is {IsValid: true}) { yield return s; } else { handleInvalid?.Invoke(result.Errors, s); } } } }