4

I'm using FluentValidation.AspNetCore library (Version="10.3.3") for a .Net Core project.

To register validators i use this: services.AddValidatorsFromAssemblyContaining<TestValidator>();

For example i have class called Test and i can inject validator for this class like this:

    public class Service : IService
    {
        private readonly IValidator<Test> _testValidator;

        public Service(IValidator<Test> testValidator)
        {
            _testValidator = testValidator;
        }
   }

But i dont know how to inject all registered validators into my Service constructor as IEnumerable instance. So what is the correct way to do it?

8
  • If you really need all of them, the Service is doing too much... but anyhow: you could probably work around this with a factory. Commented Nov 8, 2021 at 14:03
  • Did you try injecting IEnumerable<IValidator<Test>>? Commented Nov 8, 2021 at 14:21
  • @Steven Yes. With such way i will only get validator instances which inherit IValidator<Test> but assembly contains other validators for different instances. Commented Nov 8, 2021 at 14:34
  • @Fildor I use service as Decorator for validating requests and responses. And i have assembly which contains validators for models that belongs to service. That's why i want to get all of them. Maybe factory is the way if there is no other opportunities. Commented Nov 8, 2021 at 14:36
  • So you want to inject an IEnumerable<IValidator<object>> and have that list contain all registered validators. That's impossible due to the 'limitations' of the .NET's type system. This has to do with how variance and contra-variance works. Instead of injecting all validators, you can instead try to inject some sort of mediator implementation that resolves the required validators on the fly from the IServiceProvider. Commented Nov 8, 2021 at 14:42

1 Answer 1

3

FluentValidation's AddValidatorsFromAssemblyContaining registers all validators implementing IValidator<T> from assembly as generic interface and self so you can resolve them only by concrete type or constructed generic (i.e. IValidator<Test>) i.e. it is not possible to resolve all of them as a single collection.

If you really want you can try leveraging that IValidator<T> inherits IValidator and use the following (a bit hacky) solution:

services.AddValidatorsFromAssemblyContaining(typeof(Val1));

// Only after all validators registrations
var serviceDescriptors = services
    .Where(descriptor => typeof(IValidator) != descriptor.ServiceType
           && typeof(IValidator).IsAssignableFrom(descriptor.ServiceType)
           && descriptor.ServiceType.IsInterface)
    .ToList();

foreach (var descriptor in serviceDescriptors)
{
    services.Add(new ServiceDescriptor(
        typeof(IValidator),
        p => p.GetRequiredService(descriptor.ServiceType),
        descriptor.Lifetime));
}

After that you will be able to resolve IEnumerable<IValidator>. Though not sure that this will be much help for you.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.