众所周知,在使用DataAnnotations数据验证的时候,特别是针对同一个InputDto的多个属性进行对比的时候,例如起始日期不能大于结束日期,我们需要在Attribute中知道当前InputDto对象的类型和对象值,以便进行两个属性的对比。
做到以上操作,我们需要使用ValidationAttribute.IsValid(object value, ValidationContext validationContext)方法,其中ValidationContext对象会提供当前InputDto的类型和参数值。
如果我们要实现大于或等于的特性验证,代码如下:
//大于或等于的特性验证
public class GreaterOrEqualAttribute : ValidationAttribute
{
//需要被对比的属性名称
public string PropertyName { get;}
public GreaterOrEqualAttribute(string propertyName) {
PropertyName = propertyName?.Trim()??"";
} protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(PropertyName.IsNullOrEmpty())
return new ValidationResult($"{nameof(GreaterOrEqualAttribute)}.{nameof(PropertyName)}参数不能为空值"); //获取PropertyName的属性值
var propertyInfo = validationContext.ObjectType.GetProperty(PropertyName);
var propertyValue = propertyInfo?.GetValue(validationContext.ObjectInstance, null);
//如果给定对比的值为null,则返回成功
if(propertyValue==null) return ValidationResult.Success; var thisTypeCode = Convert.GetTypeCode(value);
var thatTypeCode = Convert.GetTypeCode(propertyValue);
if(thisTypeCode!=thatTypeCode)
return new ValidationResult($"{validationContext.ObjectType.Name}.{PropertyName}与{validationContext.ObjectType.Name}.{validationContext.DisplayName}的类型不匹配"); dynamic thisValue = Convert.ChangeType(value, thisTypeCode);
dynamic thatValue = Convert.ChangeType(propertyValue, thatTypeCode);
//如果当前值大于或等于给定值,则返回成功
if(thisValue>=thatValue) return ValidationResult.Success;
return new ValidationResult(ErrorMessage.IsNullOrEmpty()? $"{validationContext.ObjectType.Name}.{PropertyName}必须大于或等于{validationContext.ObjectType.Name}.{validationContext.DisplayName}":ErrorMessage);
}
}
其中validationContext.ObjectType就是InputDto对象的类型,validationContext.ObjectInstance是InputDto对象的实例,有了这两个参数,我们可以在数据验证中尽情的操作。
接下来我们定义一个InputDto类型来测试一下,验证起始时间和结束时间。代码如下:
public class InputDto
{
//起始时间
public DateTime? BeginDate { get; set; } = DateTime.Now; //结束时间
[GreaterOrEqual(nameof(BeginDate))]
public DateTime? EndDate { get; set; } = DateTime.Now;
}
测试结果如下: