如何通过Data Annotations实现小数范围或TBD值的多类型验证
没问题!这种混合验证场景完全可以用Data Annotations搞定,甚至不用啃复杂的正则——当然如果偏好正则也有方案,下面给你两种实用思路:
方法一:自定义验证属性(推荐,逻辑清晰易维护)
这种方式最直观,你可以完全控制验证逻辑,后续修改也方便。只需要创建一个继承自ValidationAttribute的自定义属性:
using System.ComponentModel.DataAnnotations; public class DecimalOrTbdAttribute : ValidationAttribute { private readonly decimal _minValue; private readonly decimal _maxValue; public DecimalOrTbdAttribute(decimal minValue, decimal maxValue) { _minValue = minValue; _maxValue = maxValue; ErrorMessage = $"值必须是\"TBD\"或者介于{_minValue}和{_maxValue}之间的小数(最多6位小数)"; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (value == null) { return new ValidationResult("值不能为空"); } var input = value.ToString().Trim(); // 匹配TBD,这里是严格大小写匹配,如果需要不区分大小写,改成StringComparison.OrdinalIgnoreCase即可 if (string.Equals(input, "TBD", StringComparison.Ordinal)) { return ValidationResult.Success; } // 尝试解析为小数 if (decimal.TryParse(input, out decimal num)) { // 检查是否在(0, 99.999999)开区间内 if (num > _minValue && num <= _maxValue) { // 检查小数位数不超过6位 var decimalPlaces = BitConverter.GetBytes(decimal.GetBits(num)[3])[2]; if (decimalPlaces <= 6) { return ValidationResult.Success; } return new ValidationResult("小数位数不能超过6位"); } } return new ValidationResult(ErrorMessage); } }
使用方式
直接在你的模型属性上标注这个自定义属性就行:
public class YourModel { [DecimalOrTbd(0, 99.999999)] public string YourValue { get; set; } }
方法二:使用正则表达式验证
如果你想用正则一次性搞定,这里给你写好适配的表达式,并且拆解了逻辑,方便你理解:
正则表达式
^(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$
逻辑拆解
^和$:确保整个字符串完全匹配,避免部分匹配的情况TBD:直接匹配字面量"TBD"- 小数部分的规则:
0*[1-9]\d{0,1}(\.\d{1,6})?:匹配1-99的整数或带1-6位小数的数(比如5、99、12.345678)0\.\d{1,6}:匹配0开头的小数(比如0.123、0.999999),排除了纯0的情况,符合你(0-99.999999)的开区间需求
使用方式
在属性上标注RegularExpression属性:
public class YourModel { [RegularExpression(@"^(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$", ErrorMessage = "值必须是\"TBD\"或者介于0和99.999999之间的小数(最多6位小数)")] public string YourValue { get; set; } }
额外说明
如果需要允许不区分大小写的"TBD"(比如"tbd"、"Tbd"),只需要在正则开头加上(?i):
^(?i)(TBD|(0*[1-9]\d{0,1}(\.\d{1,6})?|0\.\d{1,6}))$
内容的提问来源于stack exchange,提问作者kereberos
相关产品推荐
相关产品推荐

