FluentValidation:仅验证设置了一个属性

c#

我正在努力为一个类实现一个验证器,其中应该只设置一个属性。

假设我们有以下类:

public class SomeClass
{
    public DateTime SomeDate {get; set;}
    public IEnumerable<int> FirstOptionalProperty {get; set;}
    public IEnumerable<int> SecondOptionalProperty {get; set;}
    public IEnumerable<int> ThirdOptionalProperty {get; set;}
}

这个类有一个强制性属性 - SomeDate。其他属性是可选的,只能设置一个,例如如果FirstOptionalProperty设置了 -SecondOptionalProperty并且ThirdOptionalProperty应该为空,如果SecondOptionalProperty设置了 -FirstOptionalProperty并且ThirdOptionalProperty应该为空等等。

换句话说:如果设置了 IEnumerable 道具之一 - 其他 IEnumerables 应该为空。

关于为此类类实现验证器的任何提示/想法?我唯一想到的是编写When规则块,但是这种编写代码的方式很容易出错,而且结果看起来很丑陋。

回答

您可以利用Must重载来访问整个类对象,以便您可以针对其他属性进行属性验证。有关更多详细信息,请参阅多个属性的 FluentValidation 规则。

public class SomeClassValidator : AbstractValidator<SomeClass>
{
    private const string OneOptionalPropertyMessage = "Only one of FirstOptionalProperty, SecondOptionalProperty, or ThirdOptionalProperty can be set.";

    public SomeClassValidator()
    {
        RuleFor(x => x.FirstOptionalProperty)
            .Must(OptionalPropertiesAreValid)
            .WithMessage(OneOptionalPropertyMessage);

        RuleFor(x => x.SecondOptionalProperty)
            .Must(OptionalPropertiesAreValid)
            .WithMessage(OneOptionalPropertyMessage);

        RuleFor(x => x.ThirdOptionalProperty)
            .Must(OptionalPropertiesAreValid)
            .WithMessage(OneOptionalPropertyMessage);
    }

    // this "break out" method only works because all of the optional properties
    // in the class are of the same type. You'll need to move the logic back
    // inline in the Must if that's not the case.
    private bool OptionalPropertiesAreValid(SomeClass obj, IEnumerable<int> prop)
    {
        // "obj" is the important parameter here - it's the class instance.
        // not going to use "prop" parameter.

        // if they are all null, that's fine
        if (obj.FirstOptionalProperty is null && 
            obj.SecondOptionalProperty is null && 
            obj.ThirdOptionalProperty is null)
        {
            return true;
        }

        // else, check that exactly 1 of them is not null
        return new [] 
        { 
            obj.FirstOptionalProperty is not null,
            obj.SecondOptionalProperty is not null, 
            obj.ThirdOptionalProperty is not null
        }
        .Count(x => x == true) == 1;
        // yes, the "== true" is not needed, I think it looks better
    }
}

您可以调整检查功能。就目前而言,如果您设置 2 个或更多可选属性,所有这些属性都会引发错误。这可能适合也可能不适合您的需求。

您还可RuleFor以为第一个可选属性创建ONLY,而不是所有属性,因为所有属性都将执行相同的 IsValid 代码并返回相同的消息,如果您的用户收到错误消息,他们可能会感到有点困惑OptionalProperty1 但他们没有提供那个。

这种方法的缺点是您需要在编译时知道所有属性是什么(以便您可以为其编写代码),并且如果您添加/删除可选条目,则需要维护此验证器。这个缺点对你来说可能重要也可能不重要。


以上是FluentValidation:仅验证设置了一个属性的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>