using FluentValidation; using FluentValidation.Internal; using FluentValidation.Results; namespace Recyclarr.Common.FluentValidation; public class RuntimeValidationService : IRuntimeValidationService { private readonly Dictionary _validators; private static Type? GetValidatorInterface(Type type) { return Array.Find(type.GetInterfaces(), i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IValidator<>)); } public RuntimeValidationService(IEnumerable validators) { _validators = validators .Select(x => (x, GetValidatorInterface(x.GetType()))) .Where(x => x.Item2 is not null) .ToDictionary(x => x.Item2!.GetGenericArguments()[0], x => x.Item1); } public ValidationResult Validate(object instance, params string[] ruleSets) { if (!_validators.TryGetValue(instance.GetType(), out var validator)) { throw new ValidationException($"No validator is available for type: {instance.GetType().FullName}"); } IValidatorSelector validatorSelector = ruleSets.Any() ? new RulesetValidatorSelector(ruleSets) : new DefaultValidatorSelector(); return validator.Validate(new ValidationContext(instance, new PropertyChain(), validatorSelector)); } }