Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap with FluentValidation

I am using structure map as DI framework in .net core project. My registration of fluentValidation as is follows:

public class DefaultRegistry : Registry
{
    public DefaultRegistry()
    {
        Scan(o =>
        {
            o.AssemblyContainingType<Startup>();
            o.AddAllTypesOf<IValidator>();
            o.LookForRegistries();
            o.AddAllTypesOf<Profile>();
            o.WithDefaultConventions();
        });
    }
}

Thrown error: http://pastebin.com/eDHEcCfc

I inherit validator class from AbstractValidator:

public class DefaultValidator : AbstractValidator<DefaultViewModel>

DI works when I only have one validator class, once I created second one, it breaks.

I am also using assembly search to register all instances for validators:

services
                .AddMvc()
                .AddFluentValidation(x=>x.RegisterValidatorsFromAssemblyContaining<Startup>())
like image 798
sensei Avatar asked Feb 25 '26 22:02

sensei


1 Answers

Problem resolved with Custom Validator Factory.

Implemented FluentValidation interface IValidatorFactory and injected StructureMap IContainer

using System;
using System.Reflection;
using FluentValidation;
using StructureMap;

namespace Business.Managers.Interfaces
{
    public class FluentValidatorFactory : IValidatorFactory
    {
        private readonly IContainer _container;

        public FluentValidatorFactory(IContainer container)
        {
            _container = container;
        }
        public IValidator<T> GetValidator<T>()
        {
            return (IValidator<T>)GetValidator(typeof(T));
        }

        public IValidator GetValidator(Type type)
        {
            IValidator validator;

            try
            {
                validator = CreateInstance(typeof(IValidator<>).MakeGenericType(type));
            }
            catch (Exception)
            {
                // Get base type and try to find validator for base type (used for polymorphic classes)
                var baseType = type.GetTypeInfo().BaseType;
                if (baseType == null)
                {
                    throw;
                }

                validator = CreateInstance(typeof(IValidator<>).MakeGenericType(baseType));
            }

            return validator;
        }

        public IValidator CreateInstance(Type validatorType)
        {
            return _container.GetInstance(validatorType) as IValidator;
        }
    }
}

Also resolving correct validator by custom service:

using FluentValidation;
using FluentValidation.Results;

namespace Business.Managers.Interfaces
{
    public class ValidationManager : IValidationManager
    {
        private readonly IValidatorFactory _validatorFactory;

        public ValidationManager(IValidatorFactory validatorFactory)
        {
            _validatorFactory = validatorFactory;
        }

        public ValidationResult Validate<T>(T entity) where T : class
        {
            var validator = _validatorFactory.GetValidator(entity.GetType());
            var result = validator.Validate(entity);
            return result;
        }
    }
}

In startup.cs register validators with AddFluentValidation

services.AddMvc().AddFluentValidation(x=>x.RegisterValidatorsFromAssemblyContaining<LoansRequestValidator>());
like image 97
sensei Avatar answered Feb 27 '26 10:02

sensei