构造属于自己的数据模型验证
在某些情况,我们需要自己构造类似System.ComponentModel.DataAnnotations数据模型验证。让代码变得整洁,验证简单。话不多说,直接上码:
构造抽象基类ValidatorAttribute,方便扩展验证类
public abstract class ValidatorAttribute : Attribute { public string ErrorMessage { get; set; } public abstract bool IsValid(object obj); }
构造一个验证必填项类RequiredAttribute,同理,可以构造电话验证,邮箱验证,字符串长度验证等等通用验证。
public class RequiredAttribute : ValidatorAttribute { public RequiredAttribute() { this.ErrorMessage = "必要项"; } public override bool IsValid(object obj) { return obj != null; } }
模型验证方法
public class ModelValidationHandler { private static void ThrowMessage(string message) { //异常输出 Console.WriteLine(message); } public static void Validation(object obj) { Type type = obj.GetType(); var interfaces = type.GetInterfaces(); if (interfaces.Length > 0) { if (interfaces.Contains(typeof(IEnumerable))) { //如果是数组类 int count = Convert.ToInt32(type.GetProperty("Count").GetValue(obj, null)); for (int j = 0; j < count; j++) { object listItem = type.GetProperty("Item").GetValue(obj, new object[] { j }); Validation(listItem);//递归调用 } return; } } //对象属性读取 var props = type.GetProperties(); foreach (var propertyInfo in props) { var value = propertyInfo.GetValue(obj, null);//对象属性值读取 if (propertyInfo.PropertyType.Name.ToLower() == "string")//字符串属性 { //string类型,值空或null统一转换成null var str = (string)value; if (string.IsNullOrEmpty(str)) { value = null;//默认为null } } if (value == null) { //检查是不是必填项 var requiredAttribute = propertyInfo.GetCustomAttributes(typeof(RequiredAttribute), true).FirstOrDefault() as RequiredAttribute; if (requiredAttribute != null) { ThrowMessage(requiredAttribute.ErrorMessage); continue; } else { continue;//非必填,值为空,继续下一个循环 } } if (propertyInfo.PropertyType.IsClass && propertyInfo.PropertyType.Name.ToLower() != "string") { //类对象,排除string类型 Validation(value);//递归调用 continue;//继续下一个循环 } else if (propertyInfo.PropertyType.IsInterface) { //数组对象 var interfacelist = propertyInfo.PropertyType.GetInterfaces(); if (interfacelist.Length > 0) { if (interfacelist.Contains(typeof(IEnumerable))) { Validation(value);//递归调用 continue;//继续下一个循环 } } } else if (propertyInfo.PropertyType.Name.ToLower() == "string" || propertyInfo.PropertyType.IsValueType) { //值类型,Nullable泛型验证 var validators = propertyInfo.GetCustomAttributes(typeof(ValidatorAttribute), true);//所有的验证属性 if (validators.Any()) { foreach (ValidatorAttribute validator in validators) { //验证 if (!validator.IsValid(value)) { //验证不通过返回异常 ThrowMessage(validator.ErrorMessage); } } } } } } }
下面我来测试验证方法
public class TestMode { [Required(ErrorMessage = "姓名必填")] public string UserName { get; set; } [Required(ErrorMessage = "年龄必填")] public int? Age { get; set; } [Required(ErrorMessage = "高度必填")] public ulong Heght { get; set; } public IList<TestModeqq> modes { get; set; } } public class TestModeqq { [Required(ErrorMessage = "姓名1必填")] public string UserName { get; set; } [Required(ErrorMessage = "年龄1必填")] public int? Age { get; set; } [Required(ErrorMessage = "高度1必填")] public ulong Heght { get; set; } }
验证测试对象,这里是单元测试
[TestMethod] public void ValidationTest() { var mode= new TestMode(); mode.modes=new List<TestModeqq>(); mode.modes.Add(new TestModeqq()); mode.modes.Add(new TestModeqq()); ModelValidationHandler.Validation(mode); }
Console.WriteLine输出结果: