.NET技术-1.0.使用反射特性简化代码(验证Model类)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET技术-1.0.使用反射特性简化代码(验证Model类)相关的知识,希望对你有一定的参考价值。

假设现在有一个学生类(Student)

    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        /// <summary>
        /// 名字
        /// </summary>
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 地址
        /// </summary>
        public string Address { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public string Sex;
    }

 

 如果需要判断某些字段(属性)是否为空,是否大于0,便有以下代码:

    public class RegexStudent
    {
        public static string ValidateStudent(Student student)
        {
            StringBuilder validateMessage = new StringBuilder();

            if (string.IsNullOrEmpty(student.Name))
            {
                validateMessage.Append("名字不能为空");
            }

            if (string.IsNullOrEmpty(student.Sex))
            {
                validateMessage.Append("性别不能为空");
            }

            if (student.Age <= 0)
            {
                validateMessage.Append("年龄必填大于0");
            }

            //...... 几百行

            // 写到这里发现不对啊,如果必填项有20多个,难道我要一直这样写吗!
            return validateMessage.ToString();
        }
    }

这样的代码,重用性不高,而且效率低。

我们可以用特性,反射,然后遍历属性并检查特性。

首先自定义一个【必填】特性类,继承自Attribute

 

    /// <summary>
    /// 【必填】特性,继承自Attribute
    /// </summary>
    public sealed class Require: Attribute
    {
        private bool isRequire;//必填

        public bool IsRequire
        {
            get { return isRequire; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="isRequire">是否必填</param>
        public Require(bool isRequire)
        {
            this.isRequire = isRequire;
        }
    }

 

 

然后用这个自定义的特性标记学生类的成员属性: 

    /// <summary>
    /// 学生类
    /// </summary>
    public class Student
    {
        /// <summary>
        /// 名字
        /// </summary>
        private string name;

        [Require(true)]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// 年龄
        /// </summary>
        [Require(true)]
        public int Age { get; set; }

        /// <summary>
        /// 地址
        /// </summary>
        [Require(true)]
        public string Address { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        [Require(true)]
        public string Sex;
    }

 

 通过特性检查类的属性:

 

    public class RegexStudent
    { 
        public static string CheckRequire<T>(T instance)
        {
            StringBuilder validateMsg = new StringBuilder();

            Type t = typeof(T);

            var propertyInfos = t.GetProperties();
            //有人会发现,Sex也标记了[Require(true)],为什么没有验证信息,
            //这是因为,Sex没有实现属性{ get; set; },GetProperties是获取不到的。

            foreach (var propertyInfo in propertyInfos)
            {
                Require require = (Require)Attribute.GetCustomAttribute(propertyInfo, typeof(Require));
                
                //没标记,直接跳过
                if (require == null)
                {
                    continue;
                }

                //获取属性的数据类型
                var type = propertyInfo.PropertyType.ToString().ToLower();

                //获取该属性的值
                var value = propertyInfo.GetValue(instance, null);

                switch (type)
                {
                    case "system.string":
                        {
                            if (string.IsNullOrEmpty((string)value) && require.IsRequire)
                            {
                                validateMsg.Append(propertyInfo.Name).Append("不能为空").Append(",");
                            }
                        }
                        break;

                    case "system.int":
                    case "system.int32":
                    case "system.int64":
                        {
                            if ((int)value == 0 && require.IsRequire)
                            {
                                validateMsg.Append(propertyInfo.Name).Append("必须大于0").Append(",");
                            }
                        }
                        break;
                }
            }

            return validateMsg.ToString().TrimEnd(,);
        }
    }

执行验证:

 

        protected void Page_Load(object sender, EventArgs e)
        {
            Student student = new Student();

            student.Name = "张三";

            string strMsg = RegexStudent.CheckRequire<Student>(student);

            Response.Write(strMsg);
        }

 

有人会发现,Sex也标记了[Require(true)],为什么没有验证信息,这是因为,Sex没有实现属性{ get; set; },GetProperties是获取不到的。

 

 

 

以上是关于.NET技术-1.0.使用反射特性简化代码(验证Model类)的主要内容,如果未能解决你的问题,请参考以下文章

『 再看.NET7』泛性特性使用场景

C# DLL如何保护防止被破解

C# 特性详解

NPOI+反射+自定义特性实现上传excel转List及验证

.Net C# 反射,了解只需3分钟

C# 9 新特性:代码生成器编译时反射