使用 Fluent Validation 与枚举进行大于或等于比较?

发布于 2024-12-16 16:18:46 字数 1831 浏览 0 评论 0原文

好吧,假设我正在尝试根据枚举的值有条件地验证对象,我该怎么做?

这是验证对象的示例调用。

MyObjectValidator validator = new MyObjectValidator();
ValidationResult results = validator.Validate(new MyObject());

这是具有枚举值的类的示例。

public class MyObjectValidator : AbstractValidator<MyObject>
{

    public MyObjectValidator()
    {
        RuleFor(x => x.anEnum).Equal(MyObject.MyEnum.First).SetValidator(new FirstValidator());
    }

}

public class FirstValidator : AbstractValidator<MyObject>
{

    public FirstValidator()
    {
        RuleFor(x => x.someDecimal).Equal(1).WithMessage("Decimal must equal 5 with anEnum set to First");
    }

}

public class MyObject
{

    public enum MyEnum : int
    {
        First = 0,
        Second = 1,
        Third = 2
    }

    public decimal someDecimal { get; set; }
    public MyEnum anEnum { get; set; }

    public MyObject()
    {
        anEnum = MyEnum.First;
        someDecimal = 5;
    }
}

这个特定的示例抛出消息:“验证器‘FirstValidator’无法验证类型‘MyEnum’的成员 - 类型不兼容。”

经过一些编辑后,我想出了一个包装器来完成我所希望的事情,但我更喜欢一个更优雅的解决方案。我将 MyObjectValidator 替换为

public MyObjectValidator()
{
    RuleFor(x => x.anEnum).SetValidator(new ValidatorWrapper<MyObject>()).When(x => x.anEnum == MyObject.MyEnum.First);
}

并添加了验证器包装器

public class ValidatorWrapper<T> : PropertyValidator
{

    public ValidatorWrapper() : base("Validator Message")
    {
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        MyObject myObj = (MyObject)context.Instance;
        FirstValidator validator = new FirstValidator();
        ValidationResult results = validator.Validate(myObj);
    }
}

有没有一种方法可以引用内部上下文而无需提供 propertyvalidator 包装器,以便我可以根据枚举值有条件地验证多个规则?

Ok, let's say I'm trying to validate an object conditionally based upon the value of an enum, how can I do that?

Here's a sample call to validate the object.

MyObjectValidator validator = new MyObjectValidator();
ValidationResult results = validator.Validate(new MyObject());

Here's a sample of a class with an Enum Value.

public class MyObjectValidator : AbstractValidator<MyObject>
{

    public MyObjectValidator()
    {
        RuleFor(x => x.anEnum).Equal(MyObject.MyEnum.First).SetValidator(new FirstValidator());
    }

}

public class FirstValidator : AbstractValidator<MyObject>
{

    public FirstValidator()
    {
        RuleFor(x => x.someDecimal).Equal(1).WithMessage("Decimal must equal 5 with anEnum set to First");
    }

}

public class MyObject
{

    public enum MyEnum : int
    {
        First = 0,
        Second = 1,
        Third = 2
    }

    public decimal someDecimal { get; set; }
    public MyEnum anEnum { get; set; }

    public MyObject()
    {
        anEnum = MyEnum.First;
        someDecimal = 5;
    }
}

This particular example throws the message: "The validator 'FirstValidator' cannot validate members of type 'MyEnum' - the types are not compatible."

After some editing, I came up with a wrapper to do what I'm hoping, but I'd prefer a more elegant solution. I replaced MyObjectValidator with

public MyObjectValidator()
{
    RuleFor(x => x.anEnum).SetValidator(new ValidatorWrapper<MyObject>()).When(x => x.anEnum == MyObject.MyEnum.First);
}

And added a validator wrapper

public class ValidatorWrapper<T> : PropertyValidator
{

    public ValidatorWrapper() : base("Validator Message")
    {
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        MyObject myObj = (MyObject)context.Instance;
        FirstValidator validator = new FirstValidator();
        ValidationResult results = validator.Validate(myObj);
    }
}

Is there a way to reference the inner context without having to provide the propertyvalidator wrapper such that I can conditionally validate a number of rules based upon an enum value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心凉 2024-12-23 16:18:46

您看到的错误(“验证器 'FirstValidator' 无法验证类型 'MyEnum' 的成员 - 类型不兼容”)是因为通过使用 SetValidator,您尝试验证 anEnum 属性使用 FirstValidator (只能验证 MyObject 的实例) - 这不是正确的方法。如果要根据枚举属性触发规则,则需要使用FluentValidation对条件的支持。

如果您只有一个要应用条件的规则,那么您可以执行以下操作:

public class MyObjectValidator : AbstractValidator<MyObject> {

  public MyObjectValidator() {
      RuleFor(x => x.someDecimal).Equal(1).When(x => x.anEnum == MyObject.MyEnum.First);
  }

}

...或者,如果您想将相同的条件应用于多个规则,您可以使用顶部的单个条件-level When 方法:

public class MyObjectValidator : AbstractValidator<MyObject> {

    public MyObjectValidator() {
        When(x => x.anEnum == MyObject.MyEnum.First, () => {
            RuleFor(x => x.someDecimal).Equal(1);
            //other rules can go here
        });
    }

}

The error you're seeing ("The validator 'FirstValidator' cannot validate members of type 'MyEnum' - the types are not compatible") is because by using SetValidator you're trying to validate the anEnum property with FirstValidator (which can only validate instances of MyObject) - this isn't the correct approach. If you want to trigger rules based on the enum property, you need to use FluentValidation's support for conditions.

If you've only got a single rule to which you want to apply the condition, then you can do this:

public class MyObjectValidator : AbstractValidator<MyObject> {

  public MyObjectValidator() {
      RuleFor(x => x.someDecimal).Equal(1).When(x => x.anEnum == MyObject.MyEnum.First);
  }

}

...alternatively, if you want to apply the same condition to multiple rules, you can use a single condition using the top-level When method:

public class MyObjectValidator : AbstractValidator<MyObject> {

    public MyObjectValidator() {
        When(x => x.anEnum == MyObject.MyEnum.First, () => {
            RuleFor(x => x.someDecimal).Equal(1);
            //other rules can go here
        });
    }

}
初熏 2024-12-23 16:18:46

您正在使用 CLR 的 Object.Equals(),您需要使用 Equal() 或库提供的任何其他方法。

You're using the CLR's Object.Equals(), you need to use Equal() or whatever else the library provides.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文