[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
public class MinFieldAttribute : BaseCompareAttribute
{
public string MinValueField { get; set; }
private string MinDisplayName { get; set; }
public MinFieldAttribute(Type operandType, string minValueField,string minDisplayName) : base(operandType, minValueField, () => LocalizationExtensions.T("Rundong.Infrastructure.MinFieldAttribute.ErrorMsg", "{0}不能小于{1}"))
{
MinValueField = minValueField;
MinDisplayName = minDisplayName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var minPropertyInfo = validationContext.ObjectType.GetProperty(MinValueField);
if (minPropertyInfo == null)
{
return new ValidationResult(string.Format(CultureInfo.CurrentCulture, LocalizationExtensions.T("Rundong.Infrastructure.MinFieldAttribute.NotExist", "{0}不存在"), MinValueField));
}
var minPropertyValue = minPropertyInfo.GetValue(validationContext.ObjectInstance, null);
var compareValue = (IComparable) value;
if (value!=null&& compareValue.CompareTo(minPropertyValue)<0)
{
if (MinDisplayName == null)
{
MinDisplayName = ModelMetadataProviders.Current.GetMetadataForProperty(
() => validationContext.ObjectInstance, validationContext.ObjectType, MinValueField).GetDisplayName();
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name, MinDisplayName??MinValueField);
}
}
知识兔
public class MinFieldValidationMetadata<TValueType> : ModelValidationMetadata where TValueType : struct
{
public string MinValueField { get; set; }
protected override ModelValidator CreateValidatorCore(ExtendedModelMetadata modelMetadata,
ControllerContext context)
{
var type = typeof(TValueType?).GetUnderlyingType();
var minModelMetadata= modelMetadata.Properties.FirstOrDefault(a => a.PropertyName == MinValueField);
var minDisplayName = minModelMetadata!=null ? minModelMetadata.GetDisplayName() : ModelMetadataProviders.Current.GetMetadataForProperty(() => null, modelMetadata.ContainerType, MinValueField).GetDisplayName();
var attribute = new MinFieldAttribute(type, MinValueField, minDisplayName);
return new BaseCompareAttributeAdapter(modelMetadata, context, attribute){MinValueField = MinValueField };
}
}
知识兔通过重写IsValid方向添加自定义验证,MinValueField为需要比较的字段名,MinDisplayName是显示的名字。BaseCompareAttribute记录的构造函数第三个参数为重写FormatErrorMessage函数,以及提供比较值的类型转换
具体是参考微软两个字段比较是否相同https://github.com/aspnet/AspNetWebStack/blob/master/src/System.Web.Mvc/CompareAttribute.cs