I need to pass a parameter from a parent validator to a child validator, by using .SetValidator()
but having trouble with registering a validator to the DI container using FluentValidation's automatic registration, when the validator is parameterized.
Parent Validator:
public class FooValidator: AbstractValidator<Foo>
{
public FooValidator()
{
RuleFor(foo => foo.Bar)
.SetValidator(foo => new BarValidator(foo.SomeStringValue))
.When(foo => foo.Bar != null);
}
}
Child Validator:
public class BarValidator: AbstractValidator<Bar>
{
public BarValidator(string someStringValue)
{
RuleFor(bar => bar.Baz)
.Must(BeValid(bar.Baz, someStringValue)
.When(bar => bar.Baz != null);
}
private static bool BeValid(Baz baz, string someStringValue)
{
return baz == someStringValue;
}
}
DI registration
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly(), ServiceLifetime.Transient);
Error message
System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: FluentValidation.IValidator`1[Domain.ValueObjects.Bar] Lifetime: Transient ImplementationType: Application.Common.Validators.BarValidator':
Unable to resolve service for type 'System.String' while attempting to activate 'Application.Common.Validators.BarValidator'.)
---> System.InvalidOperationException: Unable to resolve service for type 'System.String' while attempting to activate 'Application.Common.Validators.BarValidator'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor serviceDescriptor, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor descriptor)
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
--- End of inner exception stack trace ---
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Program.<Main>$(String[] args) in C:\Program.cs:line 9
- .NET 7
- FluentValidation v11.2.2
- Microsoft.Extensions.DependencyInjection
Any ideas?
Have tried circumventing the use of automatic registration by filtering it out and registering it manually, but this changes nothing.
_ = services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly(), ServiceLifetime.Transient, filter => filter.ValidatorType != typeof(BarValidator));
_ = services.AddTransient<IValidator<Bar>>(_ => new BarValidator(""));