如何用When重写FluentValidation的链式AND规则验证逻辑?
使用FluentValidation的When重写链式AND逻辑验证
问题描述
我编写了如下FluentValidation验证代码:
public ActivityValidator(IUserAccessor userAccessor) { var userId = userAccessor.GetUserIdFromAccessToken(); RuleSet("CompleteHappeningAsync", () => { RuleFor(a => a.ActivityTypeId).IsHappening() .WithState(x => new BadRequest("Aktivnost nije Događaj")) .DependentRules(() => { RuleFor(a => a.EndDate).LessThanOrEqualTo(DateTimeOffset.Now) .WithState(x => new BadRequest("Događaj se još nije završio")) .DependentRules(() => { RuleFor(a => a.EndDate).GreaterThan(DateTimeOffset.Now.AddDays(-7)) .WithState(x => new BadRequest("Prošlo je nedelju dana od završetka Događaja")) .DependentRules(() => { RuleFor(a => a.User.Id).Equal(userId) .WithState(x => new BadRequest("Ne možete završiti tuđi događaj")) .DependentRules(() => { RuleFor(a => a.HappeningMedias).Empty() .WithState(x => new BadRequest("Već ste završili događaj")); }); }); }); }); }); }
请问如何使用官方推荐的When方式重写这段以AND逻辑链式的验证?注意CascadeMode仅适用于单个属性的链式规则,无法适用于当前场景。
重写后的代码
可以通过嵌套When方法实现这种顺序依赖的AND逻辑,每个后续验证仅在前序验证通过时执行,重写后的代码如下:
public ActivityValidator(IUserAccessor userAccessor) { var userId = userAccessor.GetUserIdFromAccessToken(); var now = DateTimeOffset.Now; // 提取当前时间,避免多次计算产生不一致 RuleSet("CompleteHappeningAsync", () => { // 1. 验证ActivityTypeId属于活动类型 RuleFor(a => a.ActivityTypeId) .IsHappening() .WithState(x => new BadRequest("Aktivnost nije Događaj")); // 2. 仅当ActivityTypeId验证通过时,验证活动已结束 When(a => a.ActivityTypeId.IsHappening(), () => { RuleFor(a => a.EndDate) .LessThanOrEqualTo(now) .WithState(x => new BadRequest("Događaj se još nije završio")); // 3. 仅当活动已结束时,验证结束时间未超过7天 When(a => a.EndDate <= now, () => { RuleFor(a => a.EndDate) .GreaterThan(now.AddDays(-7)) .WithState(x => new BadRequest("Prošlo je nedelju dana od završetka Događaja")); // 4. 仅当结束时间在7天内时,验证用户是活动所有者 When(a => a.EndDate > now.AddDays(-7), () => { RuleFor(a => a.User.Id) .Equal(userId) .WithState(x => new BadRequest("Ne možete završiti tuđi događaj")); // 5. 仅当用户是所有者时,验证活动未被完成过(媒体列表为空) When(a => a.User.Id == userId, () => { RuleFor(a => a.HappeningMedias) .Empty() .WithState(x => new BadRequest("Već ste završili događaj")); }); }); }); }); }); }
关键说明
- 固定当前时间:将
DateTimeOffset.Now提前赋值给变量now,避免多次验证中获取到不同时间,保证逻辑一致性。 - 嵌套When逻辑:每个
When的条件对应前序验证的通过规则,完美匹配原代码的链式依赖关系,只有前序验证通过才会触发后续验证。 - 保持行为一致:所有错误提示和状态返回与原代码完全相同,验证逻辑没有改变。
- 替代DependentRules:官方推荐用嵌套
When替代深层嵌套的DependentRules,代码可读性更强,维护成本更低。
内容的提问来源于stack exchange,提问作者Marwilpuk
相关产品推荐
相关产品推荐

