特性

SunnyFan大约 6 分钟约 1814 字

特性

什么是特性,特性的本质

Serializable:只要是标记Serializable,就可以序列化

Serializable:还可以影响我们这个编译器

特性和注释的区别---看看特性的本质

如何自定义特性,特性的多种标记

如何调用到特性内部的成员--自定义的这个特性,如果才能使用它呢

{
    Student student = new Student()
    {
        Id = 123,
        Name = "我与春风皆过客"
    };
    //student.custom//调用不到 
    InvokeAttributeManager.Show(student);
}
{
    public class InvokeAttributeManager
    {
        /// <summary>
        /// 通过反射来调用特性---确实是可以调用到特性的实例的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public static void Show(Student student)
        {
            //Type type = typeof(Student);
            Type type = student.GetType(); 
            //1.先判断是否有特性
            if (type.IsDefined(typeof(CustomAttribute), true))
            { 
                //2.获取--先判断再获取--为了提高性能
                foreach (CustomAttribute attribute in type.GetCustomAttributes(true))
                {
                    Console.WriteLine($"attribute._Name:{attribute._Name}");
                    Console.WriteLine($"attribute._Age:{attribute._Age}"); 
                    attribute.Do();
                }
            }

            //获取当前Type下所有的属性上标记的特性
            foreach (PropertyInfo prop in type.GetProperties())
            {
                if (prop.IsDefined(typeof(CustomAttribute), true))
                {
                    //2.获取--先判断再获取--为了提高性能
                    foreach (CustomAttribute attribute in prop.GetCustomAttributes(true))
                    {
                        Console.WriteLine($"attribute._Name:{attribute._Name}");
                        Console.WriteLine($"attribute._Age:{attribute._Age}");
                        attribute.Do();
                    }
                }
            }

            //获取当前Type下所有的字段上标记的特性
            foreach (FieldInfo field in type.GetFields())
            {
                if (field.IsDefined(typeof(CustomAttribute), true))
                {
                    //2.获取--先判断再获取--为了提高性能
                    foreach (CustomAttribute attribute in field.GetCustomAttributes(true))
                    {
                        Console.WriteLine($"attribute._Name:{attribute._Name}");
                        Console.WriteLine($"attribute._Age:{attribute._Age}");
                        attribute.Do();
                    }
                }
            }

            //获取当前Type下所有的方法上标记的特性
            foreach (MethodInfo method in type.GetMethods())
            {
                foreach (ParameterInfo para in method.GetParameters())
                {
                    if (para.IsDefined(typeof(CustomAttribute), true))
                    {
                        //2.获取--先判断再获取--为了提高性能
                        foreach (CustomAttribute attribute in para.GetCustomAttributes(true))
                        {
                            Console.WriteLine($"attribute._Name:{attribute._Name}");
                            Console.WriteLine($"attribute._Age:{attribute._Age}");
                            attribute.Do();
                        }
                    }
                }

                if (method.IsDefined(typeof(CustomAttribute), true))
                {
                    //2.获取--先判断再获取--为了提高性能
                    foreach (CustomAttribute attribute in method.GetCustomAttributes(true))
                    {
                        Console.WriteLine($"attribute._Name:{attribute._Name}");
                        Console.WriteLine($"attribute._Age:{attribute._Age}");
                        attribute.Do();
                    }
                }
            }
        }
    }
}

特性获取额外信息

{
    //一、传统方式获取枚举
    {
        //UserStateEnum userState = UserStateEnum.Normal;
        ////1.传统方式如果要获取到描述--只能一层一层的判断
        ////2.你们觉得这样好吗?
        ////问题:
        ////   a.分支判断太多了--如果增加一个枚举字段---就需要增加一个判断
        ////   b.如果说描述信息改了呢?只要是是使用到这个枚举的地方--都需要修改这个描述信息----工作量剧增
        //if (userState == UserStateEnum.Normal)
        //{
        //    Console.WriteLine("正常状态");
        //}
        //else if (userState == UserStateEnum.Frozen)
        //{
        //    Console.WriteLine("已冻结");
        //}
    }
    //....
    //二.通过特性来获取描述信息---额外信息--特性获取额外信息
    {
        //1.特性获取描述信息---获取额外信息
        //好处:
        //  a.如果增加字段,就可以直接获取不用其他的改动
        //  b.描述修改后,获取描述信息的方法不用修改
        //2.通过反射+特性+扩展方法,可以封装一个获取额外新的的公共方法
        {
            UserStateEnum normal = UserStateEnum.Normal;
            UserStateEnum frozen = UserStateEnum.Frozen;
            UserStateEnum deleted = UserStateEnum.Deleted;
            UserStateEnum other = UserStateEnum.Other;
            UserStateEnum other1 = UserStateEnum.Other1;
            string strnormalRemark = RemarkAttributeExtension.GetRemark(normal);
            string strfrozenRemark = RemarkAttributeExtension.GetRemark(frozen);
            string strdeletedRemark = RemarkAttributeExtension.GetRemark(deleted);
            string strotherRemark = RemarkAttributeExtension.GetRemark(other);
            string strother1Remark = RemarkAttributeExtension.GetRemark(other1);
        }
        {
            UserStateEnum normal = UserStateEnum.Normal;
            UserStateEnum frozen = UserStateEnum.Frozen;
            UserStateEnum deleted = UserStateEnum.Deleted;
            UserStateEnum other = UserStateEnum.Other;
            UserStateEnum other1 = UserStateEnum.Other1;
            string strnormalRemark = normal.GetRemark();
            string strfrozenRemark = frozen.GetRemark();
            string strdeletedRemark = deleted.GetRemark();
            string strotherRemark = other.GetRemark();
            string strother1Remark = other1.GetRemark();
        }
        {
            // //从数据库中查询出来一条数据; 
            UserInfo user = new UserInfo()
            {
                Id = 1234,
                Name = "暖风昔人",
                Age = 25,
                State = UserStateEnum.Normal
            };
            Console.WriteLine($"当前用户的状态为:{user.UserStateDescription}");
            UserInfo user1 = new UserInfo()
            {
                Id = 1234,
                Name = "暖风昔人",
                Age = 25,
                State = UserStateEnum.Frozen
            };
            Console.WriteLine($"当前用户的状态为:{user1.UserStateDescription}");
            UserInfo user2 = new UserInfo()
            {
                Id = 1234,
                Name = "暖风昔人",
                Age = 25,
                State = UserStateEnum.Deleted
            };
            Console.WriteLine($"当前用户的状态为:{user2.UserStateDescription}");
            //编程这事儿,代码写的精妙了以后,其实一门艺术;
        }
    }
}

特性获取额外功能--在之前的基础上,新增一个功能

{
    //1.如果要保存一条数据到数据库中去
    //2.从前端提交过来的数据格式为:
    //  {
    //     "id": 0,
    //     "name": "string",
    //     "age": 0,
    //     "state": 1
    //   }
    //3.包含了很多字;
    //4.如果数据库总Name的值要求存储的长度为40个字符--如果保存的数据超过40个字符---肯定会报错
    //5.肯定要在保存之前就需要验证这行数据
    //前端提交过来的数据 
    UserInfo adduse = new UserInfo()
    {
        Id = 123,
        Name = "456464",
        Age = 25,
        Mobile = "sdfsdf"
    };
    //六-一
    //1.传统方式:
    //问题:
    /// a. 太多的if判断
    /// b. 代码量太多
    {
        if (adduse.Name == null)
        {
            Console.WriteLine("不能为空");
        }
        if (adduse.Name.Length > 40)
        {
            Console.WriteLine("Name超长了");
        }
        if (adduse.Mobile.Length != 11)
        {
            Console.WriteLine("手机号有问题");
        }
    }
    //六--二//特性了获取额外功能---特性来完成验证
    {
        //增加了一个特性:可以对一个实体中的字段做验证-和验证不能为空
        //1.通过特性加反射额外的获取了一个功能
        //2.实体验证==特性获取额外信息+特性获取额外的来完成的
        //好处:
        //1.只要是把验证的规则特性定义好,就可以重新使用
        //2.如果需要验证哪个属性,就把特性标记在哪个属性上就可以了;
        //3.只是标记了一个特性,就可以获取了一个验证的逻辑
        ApiResult bResult = ValidateInvokeManager.ValiDate<UserInfo>(adduse); 
        //验证一下QQ
        //5位数---12位数 
    } 
}
{
    public static class ValidateInvokeManager
    {
        public static ApiResult ValiDate<T>(this T t) where T : class
        {
            //typeof(T);
            Type type = t.GetType();
            {
                //#region 判断是否为空
                //foreach (PropertyInfo prop in type.GetProperties())
                //{
                //    if (prop.IsDefined(typeof(RequiredAttribute), true))
                //    {
                //        RequiredAttribute attribute = prop.GetCustomAttribute<RequiredAttribute>();
                //        object oValue = prop.GetValue(t);
                //        ApiResult result = attribute.Validate(oValue);
                //        if (result.Success == false)
                //        {
                //            return result;
                //        }
                //    }
                //}
                //#endregion

                //#region 如果要判断长度
                //foreach (PropertyInfo prop in type.GetProperties())
                //{
                //    if (prop.IsDefined(typeof(LengthAttribute), true))
                //    {
                //        LengthAttribute attribute = prop.GetCustomAttribute<LengthAttribute>();
                //        object oValue = prop.GetValue(t);
                //        ApiResult result = attribute.Validate(oValue);
                //        if (result.Success == false)
                //        {
                //            return result;
                //        }
                //    }
                //}
                //#endregion
            }
            { 
                foreach (PropertyInfo prop in type.GetProperties())
                {
                    if (prop.IsDefined(typeof(AbstractAttribute), true))
                    {
                        object oValue = prop.GetValue(t); 
                        foreach (AbstractAttribute attribute in prop.GetCustomAttributes())
                        {
                            ApiResult apiResult = attribute.Validate(oValue);
                            if (apiResult.Success==false)
                            {
                                return apiResult;
                            }
                        } 
                    }
                }
            }
            //....
             
            //如果还有更多的验证呢?难道每一个验证都这样写一下?
            //抽象父类  特性 继承;

            return new ApiResult() { Success = true };
        }
    }
}