【问题标题】:How to validate a decimal to be greater than zero using ValidationAttribute如何使用 ValidationAttribute 验证小数是否大于零
【发布时间】:2019-01-23 16:47:52
【问题描述】:

我为整数创建了一个自定义验证器来检查大于 0 的输入。它工作正常。

整数的自定义验证

using System;
using System.ComponentModel.DataAnnotations;

public class GeaterThanInteger : ValidationAttribute
    {
        private readonly int _val;

        public GeaterThanInteger(int val)
        {
            _val = val;
        }   

        public override bool IsValid(object value)
        {
            if (value == null) return false;            
            return Convert.ToInt32(value) > _val;
        }       
    }

调用代码

[GeaterThanInteger(0)]
public int AccountNumber { get; set; }

十进制的自定义验证器

我正在尝试为十进制创建类似的验证器以检查大于 0 的输入。但是这次我遇到了编译器错误。

public class GreaterThanDecimal : ValidationAttribute
{
    private readonly decimal _val;

    public GreaterThanDecimal(decimal val)
    {
        _val = val;
    }

    public override bool IsValid(object value)
    {
        if (value == null) return false;
        return Convert.ToDecimal(value) > _val;
    }
}

调用代码

[GreaterThanDecimal(0)]
public decimal Amount { get; set; }

编译器错误(指向 [GreaterThanDecimal(0)])

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

我尝试了几种组合,

[GreaterThanDecimal(0M)]
[GreaterThanDecimal((decimal)0)]

但不起作用。

我查看了ValidationAttribute 定义和文档,但我仍然迷路了。

抱怨的错误是什么?

在这种情况下,是否有其他方法可以验证大于 0 的小数?

【问题讨论】:

  • 我认为在这种情况下您可以使用 Range 属性。无需为此实施自定义验证。希望能帮到你,我的朋友!
  • @Tomato32 谢谢。但是对于 Range,我需要定义最小值和最大值。定义大于 0 的最小最小值会很棘手,特别是对于小数。另外我不想设置最大限制约束。这就是为什么我只是试图将其定义为 - 大于 0 的小数。
  • 有什么理由不能使用 double/int 来设置要比较的初始值吗?如果您只是检查它是否大于 0,那么您的属性可以接受一个整数参数来与小数进行比较。
  • @JonathonChase 谢谢。从您共享的链接中读取 - “基本类型不是基本类型的小数,因此不能在元数据中表示,这会阻止它成为属性参数。” - 这个错误现在完全有道理了。是的,我可以把它改成双倍,它可以工作。

标签: c# .net validation c#-5.0 custom-validators


【解决方案1】:

使用范围属性。也适用于小数。

[Range(0.01, 99999999)]

【讨论】:

    【解决方案2】:

    @JonathonChase 在 cmets 中回答了这个问题,我想我会在这里用修改后的代码示例完成答案,以防有人偶然发现这个问题。

    抱怨的错误是什么?

    因为调用 [GreaterThanDecimal(0)] 试图将十进制作为属性参数传递,所以 CLR 不支持。见use decimal values as attribute params in c#?

    解决方案

    将参数类型改为double或int

    public class GreaterThanDecimalAttribute : ValidationAttribute
        {
            private readonly decimal _val;
    
    
            public GreaterThanDecimalAttribute(double val) // <== Changed parameter type from decimal to double
            {
                _val = (decimal)val;
            }
    
            public override bool IsValid(object value)
            {
                if (value == null) return false;
                return Convert.ToDecimal(value) > _val;
            }
        }
    

    【讨论】:

    • 按照惯例,所有的属性类都应该以Attribute为后缀。
    • double 的精度与decimal 的精度不同。你可能会遇到惊喜。为了安全起见,您的属性应该具有与 decimal 结构相同的构造函数重载。
    • @PauloMorgado,在我的用例中丢失一些精度是可以接受的。将 ctor(decimal) 和 ctor(double) 并排放置,编译器会抱怨两者之间的调用不明确。
    • 在你被它咬之前都可以接受。一个以 2 为底,另一个以 10 为底。
    猜你喜欢
    • 2016-07-29
    • 1970-01-01
    • 2022-12-07
    • 1970-01-01
    • 2019-02-23
    • 2011-03-20
    • 1970-01-01
    • 2019-06-08
    相关资源
    最近更新 更多