You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Fluent Validation验证数组中Stop对象的AppointmentDateTime按先后顺序递增

如何使用Fluent Validation验证数组中Stop对象的AppointmentDateTime按先后顺序递增

嗨,我完全懂你的需求——就是要确保Stops数组里的每个后续站点的预约时间都比前一个晚对吧?Fluent Validation自带的RuleForEach确实只能单个校验元素,没法直接记录前一个元素的状态,但咱们可以通过自定义集合验证规则来搞定这个问题。

其实很简单,咱们直接给整个Stops数组加一条Must规则,在规则里自己实现循环比较逻辑就行,具体代码示例如下:

// 针对整个Stops数组添加顺序验证规则
RuleFor(x => x.Stops)
    .Must(stops =>
    {
        // 如果数组为空或者只有一个元素,直接通过验证
        if (stops == null || stops.Count <= 1)
            return true;

        DateTime? previousAppointmentTime = null;
        foreach (var stop in stops)
        {
            // 这里其实你之前的ChildRule已经校验过时间不为空,不过加一层保险更严谨
            if (stop.AppointmentDateTime == null)
                return false;

            // 对比当前站点和前一个站点的时间
            if (previousAppointmentTime.HasValue && stop.AppointmentDateTime <= previousAppointmentTime)
                return false;

            // 更新前一个时间为当前时间,继续循环
            previousAppointmentTime = stop.AppointmentDateTime;
        }
        return true;
    })
    .WithMessage("站点预约时间必须按先后顺序递增,每个后续站点的时间必须晚于前一个");

如果你想让错误消息更精准,能指出具体是哪两个站点出了问题,可以稍微优化一下代码,利用Fluent Validation的消息格式化器带上索引和时间信息:

RuleFor(x => x.Stops)
    .Must((parentObject, stops, validationContext) =>
    {
        if (stops == null || stops.Count <= 1)
            return true;

        DateTime? previousAppointmentTime = null;
        for (int i = 0; i < stops.Count; i++)
        {
            var currentStop = stops[i];
            if (currentStop.AppointmentDateTime == null)
                return false;

            if (previousAppointmentTime.HasValue && currentStop.AppointmentDateTime <= previousAppointmentTime)
            {
                // 给消息格式化器添加参数,方便在错误消息中显示具体信息
                validationContext.MessageFormatter.AppendArgument("StopIndex", i);
                validationContext.MessageFormatter.AppendArgument("PrevTime", previousAppointmentTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                validationContext.MessageFormatter.AppendArgument("CurrentTime", currentStop.AppointmentDateTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
                return false;
            }

            previousAppointmentTime = currentStop.AppointmentDateTime;
        }
        return true;
    })
    .WithMessage("索引为{StopIndex}的站点预约时间({CurrentTime})不晚于前一个站点的时间({PrevTime}),请调整顺序");

这个思路的核心就是:既然RuleForEach没法跨元素关联,那咱们就直接对整个集合做校验,在Must委托里自己实现需要的循环和状态记录逻辑,完全能满足你的需求。

备注:内容来源于stack exchange,提问作者SpaceCowboy74

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:44:28