代码之家  ›  专栏  ›  技术社区  ›  SpaceCowboy74 Mohammad Aghazadeh

使用Fluent Validation比较数组中的值

  •  1
  • SpaceCowboy74 Mohammad Aghazadeh  · 技术社区  · 2 月前

    我在HTTP Post正文中收到了一个对象数组。看起来像这样:

    {
      load: {
         stops: [
              { 
                Name: "Stop 1",
                AppointmentDateTime: "02/25/2025T14:00:00"
              },
              { 
                Name: "Stop 2",
                AppointmentDateTime: "02/25/2025T13:00:00"
              },
              { 
                Name: "Stop 3",
                AppointmentDateTime: "02/25/2025T15:30:00"
              }
          ]
       }
    }
    

    我已经用C#编写了一个流体验证器,可以使用以下代码:

    RuleForEach(x => x.Stops).ChildRule(stop => 
    {
       stop.RuleFor(s => s.Name).NotEmpty().NotNull();
       stop.RuleFor(s => s.AppointmentDateTime).NotEmpty().NotNull().Must(x => x > x.DateTime.Now).WithMessage("AppointmentDateTime must be in the future");
    }
    

    虽然这可行,但我想验证数组中的项是否是连续的。第2站应在第1站之后有预约时间,第3站在第2站之后等。我在代码中找不到一种方法来做类似for循环的事情,这样我就可以保存前一个项目的值。理想情况下,我会做这样的事情:

    Stop? prevStop = null;
    foreach (stop in stops) {
      if (!prevStop is null)
        {
         DO SOMETHING TO validate that prevStop.AppointmentDateTime > stop.AppointmentDateTime;
        }
      prevStop = stop;
    }
    

    虽然有一种类似foreach的测试项目的方法,但我看不出有什么方法可以保存上一个项目以与当前项目进行比较。

    1 回复  |  直到 2 月前
        1
  •  1
  •   SpaceCowboy74 Mohammad Aghazadeh    2 月前

    您可以创建 Custom Validator 如下:

    
    public class LoadValidator : AbstractValidator<Load>
    {
        public LoadValidator()
        {
            RuleForEach(x => x.Stops).ChildRule(stop =>
            {
                stop.RuleFor(s => s.Name).NotEmpty().NotNull();
                stop.RuleFor(s => s.AppointmentDateTime).NotEmpty().NotNull().Must(x => x > DateTime.Now).WithMessage("AppointmentDateTime must be in the future");
            });
    
            RuleFor(x => x.Stops).Must(stops => BeInChronologicalOrder(stops)).WithMessage("Stops must be in chronological order");
        }
    
        private bool BeInChronologicalOrder(Stop[] stops)
        {
            if (stops == null || stops.Length <= 1)
            {
                return true;
            }
    
       
            //iterate through the array
            //and compare the AppointmentDateTime of the current stop 
            //with the AppointmentDateTime of the previous stop.
            //If any stop's appointment time
            //is not after the previous stop's appointment time, the   validation fails,
            //and the method returns false.
           
            for (int i = 1; i < stops.Length; i++)
            {
                if (stops[i].AppointmentDateTime <= stops[i - 1].AppointmentDateTime)
                {
                    return false;
                }
            }
    
            return true;
        }
    }