c#模型验证数据和设置默认值( 特性验证)
封装验证特性
public abstract class ValidationAttribute : Attribute { public ValidationAttribute() { ErrorMessage = ""; Name = ""; } /// <summary> /// 错误消息 /// </summary> public string ErrorMessage { get; set; } /// <summary> /// 字段名称 /// </summary> public string Name { get; set; } /// <summary> /// 验证过程 /// </summary> /// <param name="o"></param> /// <returns></returns> public virtual bool Verify(object o) { return false; } /// <summary> /// 默认值 /// </summary> public object DefaultValue { get; set; } }
错误信息实体
public class ValidResult { public ValidResult() { ValidResultDetails = new List<ValidResultDetail>(); } public bool IsValid { get { return ValidResultDetails.Count() == 0; } } public virtual string ErrorMessage { get { string r = null; if (ValidResultDetails.Count() > 0) { r = ValidResultDetails.FirstOrDefault().ErrorMessage; } return r; } set { value = ErrorMessage; } } //错误摘要 public List<ValidResultDetail> ValidResultDetails { get; set; } } public class ValidResultDetail { public string Name { get; set; } public bool IsValid { get; set; } public virtual string ErrorMessage { get; set; } }
验证类
public class EntifyValidator { /// <summary> /// 验证完所有字段 /// </summary> public static ValidResult Validate(object data, params string[] ignore) { return new EntifyValidator().Verify(false, data, ignore); } /// <summary> /// 当有未通过的验证时,直接返回,停止验证 /// </summary> public static ValidResult ValidateQuickly(object data, params string[] ignore) { return new EntifyValidator().Verify(true, data, ignore); } /// <summary> /// /// </summary> /// <param name="quickly">验证完所有字段Or验证到未通过的立即返回</param> /// <param name="data">需要验证的数据</param> /// <param name="ignore">忽略的字段</param> /// <returns></returns> public virtual ValidResult Verify(bool quickly, object data, params string[] ignore) { ValidResult result = new ValidResult(); List<PropertyInfo> props = data.GetType().GetProperties().Where(a => !ignore.Contains(a.Name.ToLower())).ToList(); foreach (var item in props) { var validateattrs = item.GetCustomAttributes(typeof(ValidationAttribute), true); var input = item.GetValue(data, null); foreach (var itemattr in validateattrs) { var attr = ((ValidationAttribute)itemattr); if (attr != null) { attr.Name = item.Name; SetDefaultValue(data, item, attr); var isvalid = attr.Verify(input); if (string.IsNullOrEmpty(attr.ErrorMessage)) continue; if (!isvalid) { ValidResultDetail validResultDetail = new ValidResultDetail(); validResultDetail.Name = item.Name; validResultDetail.ErrorMessage = string.Format(attr.ErrorMessage, item.Name); validResultDetail.IsValid = false; result.ValidResultDetails.Add(validResultDetail); if (quickly) { return result; } } } } } return result; } /// <summary> /// 设置默认值 /// </summary> private void SetDefaultValue(object data, PropertyInfo item, ValidationAttribute attr) { var input = item.GetValue(data, null); if (attr.DefaultValue != null && input == null)//设置默认值 { item.SetValue(data, attr.DefaultValue, null); } else if (attr.DefaultValue != null && input.GetType().Name == "DateTime") { if (Convert.ToDateTime(input) == DateTime.MinValue) { item.SetValue(data, Convert.ToDateTime(attr.DefaultValue), null); } } } }
封装的简单验证特性
public class InEnumAttribute : ValidationAttribute { public InEnumAttribute() { ErrorMessage = "{0}应该在区间内"; } public Type RangeType { get; set; } public override bool Verify(object o) { if (o == null) { return false; } var r = false; foreach (var item in Enum.GetValues(RangeType)) { if (((int)item) == Convert.ToInt32(o)) { r = true; break; } } return r; } }
public class NotNullAttribute : ValidationAttribute { public bool? NotNull { get; set; } = true; public NotNullAttribute() { ErrorMessage = "{0}必填"; } public override bool Verify(object o) { if (o == null) { return false; } else if (string.IsNullOrWhiteSpace(o.ToString())) { return false; } return true; } } /// <summary> /// 默认值 /// </summary> public class DValueAttribute : ValidationAttribute { public DValueAttribute() { } }
使用方式在要验证的实体类型加特性
/// <summary> /// 转单 /// </summary> [NotNull(ErrorMessage = "转单必填")] public string cserviceno { get; set; } /// <summary> /// 修改时间 /// </summary> [DValue(DefaultValue = "1900-01-01 00:00:00")] public DateTime dlastmod { get; set; } /// <summary> /// 包裹类型 /// </summary> [InEnum(ErrorMessage = "包裹类型错误", RangeType = typeof(Nitemtype))] public Nitemtype nitemtype { get; set; }
调用
var r = EntifyValidator.Validate(rec); if (!r.IsValid) { r.ValidResultDetails.Select(item => item.ErrorMessage); }