想象一下,您有一个像这样的课程:
public enum Kind { Kind1, Kind2 }
public class MyForm
{
public string Kind { get; set; }
public ACustomClass1 Custom1 { get; set; }
public ACustomClass2 Custom2 { get; set; }
}
并且您想在Custom1
时用Custom1Validator
验证Kind == Kind1
(显然在Custom2
时用Custom2Validator
验证Kind == Kind2
)
继续使用8.6.0版的最佳方法是什么?
此刻,我已经这样做了(但是我觉得很尴尬):
public class MyFormValidator : AbstractValidator<MyForm>
{
public MyFormValidator (IStringLocalizer<Strings> localizer, Custom1Validator validator1, Custom2Validator validator2)
{
//validate Kind and then, in function of Kind, use correct validator
RuleFor(x => x).Custom((f, context) => {
if (!Enum.TryParse<Kind>(f.Kind, out var kind))
{
context.AddFailure(localizer["Invalid Kind"]);
return;
}
switch (kind)
{
case Kind.Kind1:
if (f.Custom1 == null)
{
context.AddFailure(localizer["Invalid Kind"]);
}
else if (! validator1.Validate(f.Custom1, out var firstError))
{
context.AddFailure(firstError);
}
break;
case Kind.Kind2:
if (f.Custom2 == null)
{
context.AddFailure(localizer["Invalid Kind"]);
}
else if (!validator2.Validate(f.Custom2, out var firstError))
{
context.AddFailure(firstError);
}
break;
}
});
}
}
请注意,我使用的是带有依赖项注入的asp.net核心(这就是为什么IStringLocalizer
出现在{1}和Custom2上而不能使用SetValidator
的原因)
我想要的是类似的东西
RuleFor(x => x.Kind).NotEmpty().IsEnumName(typeof(Kind)).withMessage(_ => localizer["Invalid Kind"]);
RuleFor(x => x.Custom1).NotEmptyWhen(f => f.Kind == Kind.Custom1.ToString()).withMessage(_ => localizer["Invalid Kind"])
RuleFor(x => x.Custom1).SetValidator(validator1); //would be executed only when custom1 is not null
//与custom2相同
问题是我看不到如何编写NotEmptyWhen
方法的代码
答案 0 :(得分:1)
重组?
根据已发布代码段的外观,我假设MyForm
在同一请求中永远不会具有填充的Custom1
和Custom2
属性。因此,我建议您不要直接使用表示要验证的有效负载的模型,而不要拥有同时包含两种有效负载种类的父模型。这样一来,您就不会在需要时遇到这种检查种类的讨厌模式。
您的一个表单终结点接受Custom1
,它具有关联的Custom1Validator
。您的表单端点中的另一个端点接受Custom2
,它具有关联的Custom2Validator
。它们是分离的。您可以安全地更改其中一个而不影响另一个。
使用Fluent验证条件(何时/除非)
如果您对使用一个模型负责表示多个请求的有效负载(请不要这么做)感到厌烦,可以使用该库提供的When()
方法。看看他们在conditional rules上的文档。