FluentValidation 通过 id 验证对象

FluentValidation Validate object by id

我通常使用 FluentValidation 传递 ID 与命令中的对象。但是我想验证一个带有id的对象是否存在,然后验证那个对象。

还有比下面的方法更好的方法吗?

    public class ProjectIdValidator : AbstractValidator<int>
    {

        public ProjectIdValidator(MyDbContext aDbContext)
        {
            Custom(aProjectId =>
            {
                var project = aDbContext.Projects.Find(aProjectId);
                if (project == null)
                {
                    return new ValidationFailure("ProjectId", "Project does not exist");
                }
                var projectValidator = new ProjectValidator();
                var x = projectValidator.Validate(project);
                if (x.IsValid)
                {
                    return null;
                }

                return new ValidationFailure("ProjectId", x.Errors.ToString());

            });
        }
    }

经过一番研究,我认为这是一种更好的方法。

AddRule(new DelegateValidator<Command>((aCommand, aContext) =>
{
    // return an IEnumerable<ValidationFailure> from in here:
    var projectId = (int?) aCommand.ProjectId;
    if (projectId.HasValue)
    {

        using (var dbContextScope = aDbContextScopeFactory.CreateReadOnly())
        {
            MyDbContext dbContext = dbContextScope.DbContexts.Get<MyDbContext>();
            Project project = dbContext.Projects.Find(projectId);
            if (project == null)
            {
                return Enumerable.Repeat(new ValidationFailure("ProjectId", "ProjectId not found"),1);
            }

            var projectValidator = new ProjectValidator();
            var results = projectValidator.Validate(project);

            return results.Errors;
        }
    }
    return null;
}));

这样的事情怎么样?

public class UpdateProjectCommandValidator : AbstractValidator<UpdateProjectCommand>
{
    public UpdateProjectCommandValidator(DbContext dbContext) {
        RuleFor(x => x.Id)
            .MustFindProjectById(dbContext);
    }
}

那么您的 MustFindProjectById 扩展方法将如下所示:

public static class MustFindProjectByIdExtensions {
    public static IRuleBuilderOptions<T, int> MustFindProjectById<T>
        (this IRuleBuilder<T, int> ruleBuilder, DbContext dbContext) {
        return ruleBuilder.SetValidator(new MustFindProjectById(dbContext));
    }
}

...它只是自定义 PropertyValidator:

的包装
internal class MustFindProjectById : PropertyValidator {
    private readonly DbContext _dbContext;
    internal MustFindProjectById(DbContext dbContext) {
        _dbContext = dbContext;
    }

    protected override IsValid(PropertyValidatorContext) {
        var projectId = (int)context.PropertyValue;
        var entity = dbContext.Projects.Find(projectId);
        return entity != null;
    }
}