C#--特性的运用试验

以下是学习笔记:

一,特性运用试验(一)

需求1:传统的代码

有这样一个用户状态的枚举类型:

 

namespace _015_特性.EnumExtend
{
    /// <summary>
    /// 枚举:用户的状态
    /// </summary>
    public enum UserState
    {
        /// <summary>
        /// 正常
        /// </summary>
        Normal=0,
        /// <summary>
        /// 冻结
        /// </summary>
        Frozen=1,
        /// <summary>
        /// 删除
        /// </summary>
        Deleted=2
    }
}

  

如果想要知道用户的状态,代码这样写:

            UserState userState = UserState.Frozen;
            if (userState == UserState.Normal)
            {
                Console.WriteLine("正常");
            }
            else if (userState == UserState.Frozen)
            {
                Console.WriteLine("冻结");
            }
            else if (userState == UserState.Deleted)
            {
                Console.WriteLine("删除");
            }

  

上面的代码存在这样的问题:

如果状态要改变(正常,删除,冻结,,),改代码就非常的费劲,每次都要判断很多次

需求1:运用特性后的代码思路

【1】,先定义一个特性

namespace _015_特性.EnumExtend
{
    //自定义Attribute,特性上还可以加特性
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    //参数1:可以被哪些情况下使用,如果是All就是被所有情况下都可以用。
    //参数2:是否可以标记多个特性
    //参数3:是否可以被继承
    public class RemarkAttribute:Attribute
    {
       /// <summary>
       /// 状态特性
       /// </summary>
       /// <param name="remark"></param>
        public RemarkAttribute(string remark)
        {
            this.Remark = remark;
        }

        public string Remark { get;private set; }
    }
}

  

【2】,特性定义好了之后,标记特性

namespace _015_特性.EnumExtend
{
    /// <summary>
    /// 枚举:用户的状态
    /// </summary>
    public enum UserState
    {
        /// <summary>
        /// 正常
        /// </summary>
        [Remark("正常")]
        Normal=0,
        /// <summary>
        /// 冻结
        /// </summary>
        [Remark("冻结")]
        Frozen = 1,
        /// <summary>
        /// 删除
        /// </summary>
        [Remark("删除")]
        Deleted = 2
    }
}

  

【3】写一个调用特性方法的类

namespace _015_特性.EnumExtend
{
    /// <summary>
    /// 特性调用的类,用来调用特性的
    /// </summary>
    public class AttributeInvoke
    {
        public string GetRemark(UserState userState)
        {
            Type type = userState.GetType();//获取到传过来的类型
            var fileId = type.GetField(userState.ToString());//根据参数这个值找到具体的字段
            if(fileId.IsDefined(typeof(RemarkAttribute),true)) //查找字段有没有有定义RemarkAttribute这个特性,
            {
                RemarkAttribute remarkAttribute =
                    (RemarkAttribute) fileId.GetCustomAttribute(typeof(RemarkAttribute), true);
                return remarkAttribute.Remark;//如果找到了,就返回这个特性的属性

            }
            else
            {
                return userState.ToString();//如果找不到,就返回传过来的这个值
            }
        }
    }
}

  

【4】在主程序中调用

            UserState userState2 = UserState.Frozen;
            AttributeInvoke attributeInvoke=new AttributeInvoke();
            Console.WriteLine(attributeInvoke.GetRemark(userState2));

  

改用特性的好处总结:不用if else的判断了,直接把userState2当做参数传入方法attributeInvoke.GetRemark(userState2)就可以啦。

总结上面的过程:定义特性--标记特性--调用(需要用到发射的技术)

二,特性运用试验(二),特性验证

【1】定义带特性的抽象类

namespace _015_特性.ValidateExtend
{
    /// <summary>
    /// 带有抽象方法的抽象类
    /// </summary>
    public abstract class AbstractValidateAttribute:Attribute
    {
        /// <summary>
        /// 验证数据的方法
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public abstract bool Validate(object objValue);
    }
}

  

【2】写三个实现抽象类的实现验证类

1,

namespace _015_特性.ValidateExtend
{
    [AttributeUsage(AttributeTargets.Property)]
    public class LongAttribute : AbstractValidateAttribute
    {
        private long _Long = 0;

        public LongAttribute(long phoneLength)
        {
            this._Long = phoneLength;
        }
        /// <summary>
        /// 检验手机号是否为11位
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public override bool Validate(object objValue)
        {
            return objValue != null && objValue.ToString().Length == 11;

        }
    }
}

  

2,

namespace _015_特性.ValidateExtend
{
    public class RequriedAttribute : AbstractValidateAttribute
    {
        /// <summary>
        /// 检验值是否为空
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public override bool Validate(object objValue)
        {
           return objValue != null && !string.IsNullOrWhiteSpace(objValue.ToString());
        }
    }
}

  

3,

namespace _015_特性.ValidateExtend
{
    [AttributeUsage(AttributeTargets.Property)]
    public class StringLengthAttribute : AbstractValidateAttribute
    {
        private int _Min = 0;
        private int _Max = 0;

        public StringLengthAttribute(int min,int max)
        {
            this._Min = min;
            this._Max = max;
        }
        /// <summary>
        /// 验证字符串的长度
        /// </summary>
        /// <param name="objValue"></param>
        /// <returns></returns>
        public override bool Validate(object objValue)
        {
          return  objValue != null && objValue.ToString().Length >= this._Min && objValue.ToString().Length <= this._Max;
        }
    }
}

  

【3】,写一个调用方法的类

namespace _015_特性.ValidateExtend
{
    public static class AttributeExtend
    {
        /// <summary>
        /// 调用特性的方法的类(扩展方法)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static bool Validate<T>(this T t)
        {
            Type type = t.GetType();//找到t参数的类型
            foreach (var property in type.GetProperties())//从类型里面查找遍历所有的属性
            {
                if (property.IsDefined(typeof(AbstractValidateAttribute), true)) //查找属性有没有被定义AbstractValidateAttribute特性
                {
                    object objValue = property.GetValue(t);//获取属性的值
                    foreach (AbstractValidateAttribute attribute in property.GetCustomAttributes(typeof(AbstractValidateAttribute), true))
                    {
                        if (!attribute.Validate(objValue))//如果成功了以后就继续验证,否则就直接返回
                        {
                            return false;
                        }
                    }
                }
            }

            return true;
        }
    }
}

  

【4】要验证的实体类,并标记特性

namespace _015_特性.ValidateExtend
{
    public class Student
    {
        public int Id { get; set; }
        [Requried]
        [StringLength(5,10)]
        public string StudentName { get; set; }
        [Requried]
        [Long(11)]
        public long PhoneNumber { get; set; }
    }
}

  

【5】在主程序中调用

            Student student = new Student()
            {
                Id = 1,
                PhoneNumber = 186684806622,
                StudentName = "jason cai"
            };
            if (student.Validate())
            {
                Console.WriteLine("验证成功");
            }
            else
            {
                Console.WriteLine("验证失败");
            }

  

 

posted @ 2021-01-04 22:42  包子789654  阅读(154)  评论(0编辑  收藏  举报