zoukankan      html  css  js  c++  java
  • 能递归检查DataAnnotations的验证函数

    有时在Command和DTO之间层次比较多,写了个验证Command的函数,能实现递归验证.

    比如下面这些有层级关系的class定义,能通过一句代码来进行验证:

    class A
        {
            [Required]
            public B B { get; set; }
        }
    
        class B
        {
            [Range(10, 20)]
            public int C { get; set; }
    
            [Range(typeof(Guid), "00000000-0000-0000-0000-000000000001", "00000000-0000-0000-0000-000000000010")]
            public Guid aa { get; set; }
    
            public CC ddd { get; set; }
        }
        class CC
        {
            [Range(10, 20)]
            public int DDDDD { get; set; }
    
            [Required(ErrorMessage = "必须填写用户名")]
            [Display(Name = "用户名")]
            public string UserName { get; set; }
    
            [Required(ErrorMessage = "必须填写密码")]
            [DataType(DataType.Password)]
            [Display(Name = "密码")]
            public string Password { get; set; }
        }

    验证函数调用:

    List<BrokenRule> errors = obj.IsValid();

    代码如下:

    public class BrokenRule
        {
            public string Key { get; set; }
            public string Message { get; set; }
        }
    
        public static class DataAnnotationHelper
        {
            public static List<BrokenRule> IsValid<T>(this T o, bool only1Level = false)
            {
                return IsValid(typeof(T), o, only1Level);
            }
    
            private static List<BrokenRule> IsValid(Type t, object o, bool only1Level)
            {
                List<BrokenRule> errors = new List<BrokenRule>();
    
                var descriptor = GetTypeDescriptor(t);
    
                foreach (PropertyDescriptor propertyDescriptor in descriptor.GetProperties())
                {
                    foreach (var validationAttribute in propertyDescriptor.Attributes.OfType<ValidationAttribute>())
                    {
                        if (!validationAttribute.IsValid(propertyDescriptor.GetValue(o)))
                        {
                            BrokenRule error = new BrokenRule();
                            error.Key = propertyDescriptor.Name;
                            error.Message = validationAttribute.FormatErrorMessage(propertyDescriptor.Name);
                            errors.Add(error);
                        }
                    }
                }
    
                if (!only1Level)
                {
                    if (o.GetType().IsClass&&!o.GetType().Equals(typeof(string)))
                    {
                        foreach (var p in o.GetType().GetProperties())
                        {
                            object pValue = p.GetValue(o, null);
                            if (pValue != null)
                            {
                                List<BrokenRule> pErrors = IsValid(p.PropertyType, pValue, only1Level);
                                errors.AddRange(pErrors);
                            }
                        }
                    }
                }
    
                return errors;
            }
            private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
            {
                return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
            }
        }

     效果图:

     

     完整demo代码下载

  • 相关阅读:
    vim 一些操作
    RedisTemplate 获取过期时间的问题
    SpringBoot 配置 Redis 多缓存名(不同缓存名缓存失效时间不同)
    Vue ElementUI Tree组件 回显问题(设置选择父级时会全选所有的子级,有此业务场景是不适合的)
    动态切换数据库源码解析
    @Primary 注解的作用
    @Value注解的使用
    Shiro&Jwt验证
    浏览器缓存和Service Worker
    Javascript的事件模型和Promise实现
  • 原文地址:https://www.cnblogs.com/aarond/p/Validate.html
Copyright © 2011-2022 走看看