开发者

FluentValidation as a service

开发者 https://www.devze.com 2023-02-07 10:21 出处:网络
I\'m using FluentValidation 2 for validating some entities. I\'d like to create an IValidationService that I can pass into other services to allow them to perform validation. I\'d like to expose it li

I'm using FluentValidation 2 for validating some entities. I'd like to create an IValidationService that I can pass into other services to allow them to perform validation. I'd like to expose it like this:

public interface IValidationEngine
{
    IEnumerable<ValidationError> Validate<T>(T entity);
}

Where ValidationError is a class that encapsulates my validation errors. Ideally, I'd like to not开发者_运维技巧 have to expose a specific validator to one of my services (such as OrderValidator). I'd like the validation service be capable of constructing/finding the correct validator. Does FV have anything built in for locating a validator for a specific type (and it internally caches)? Or, do I have to go the IValidatorFactory route and then wire each validator with my IoC container?


I've managed to solve this with the IValidatorFactory method. I'm using Ninject, so specific IoC details below would need to be changed.

public interface IValidationService
{
    IEnumerable<ValidationError> Validate<T>(T entity)
        where T : class;
}

public class FluentValidationService : IValidationService
{
    private readonly IValidatorFactory validatorFactory;

    public FluentValidationService(IValidatorFactory validatorFactory)
    {
        this.validatorFactory = validatorFactory;
    }

    public IEnumerable<ValidationError> Validate<T>(T entity)
        where T : class
    {
        var validator = this.validatorFactory.GetValidator<T>();
        var result = validator.Validate(entity);
        return result.Errors.Select(e => new ValidationError(e.PropertyName, e.ErrorMessage));
    }
}

// Then implement FV's IValidatorFactory:

public class NinjectValidatorFactory : ValidatorFactoryBase
{
    private readonly IKernel kernel;

    public NinjectValidatorFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        return kernel.TryGet(validatorType) as IValidator;
    }
}

// I then wire both of these in a Ninject Module:

public class ValidationModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<IValidationService>().To<FluentValidationService>().InRequestScope(); // Specific to MVC.
        this.Bind<IValidatorFactory>().To<NinjectValidatorFactory>().InRequestScope();
    }
}

// Then I can use it inside a service:

public class FooService
{
    private readonly IValidationService validationService;

    public FooService(IValidationService validationService)
    {
        this.validationService = validationService;
    }

    public bool Add(Foo foo)
    {
        if(this.validationService.Validate(foo).Any())
        {
            // Handle validation errors..
        }

        // do other implementation details here.
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号