C#特性

什么是特性?你每天上班去公司的时候,都要打开门进去公司工作。突然有一天公司倒闭了,公司的门上贴了一个封条,此时我们已经不能进去大门了,就这一个标签贴着我们就真的进不去大门了吗?那肯定不是,只不过这个封条有法律效应,你要是违反了那你就是在和法律作对。那么这个封条标签就类似于特性,它可以让你进入公司之前走一些流程,或者不让你进去公司。

  •  Attribute用来在代码中附加一些元信息,这些元信息可被编译器、.NET Framework、或者我们的程序使用。方法、属性、类等上都可以标注Attribute。
  • 命名一般以Attribute结尾,如果以Attribute结尾的话使用的时候可以省略Attribute。
  • 在Type、MethodInfo、PropertyInfo等上都可以调用object[] GetCustomAttributes(Type attributeType, bool inherit)获取标注的注解对象,因为同一个Attribute可能标注多次,所以返回值是数组。

例如Obsolete:表示该特性已过时。

 [Obsolete("该类已经过时", true)]
    public class OldClass
    {
        [method: Obsolete("该方法已经过时")]
        public void OldMethod()
        {
            Console.WriteLine("我是一个方法");
        }
    }

当我们实例化该类的时候,编译器直接告诉我们该类已过时,运行的时候直接报错。

 

 

 我们选择Obsolete按F12进去,我们可以看到ObsoleteAttribute继承Attribute,里面有Message和Error属性,再接着就是几个构造函数了。有人就会有疑问了,就这两个东西就能让编译器警告?当然不是了,之所以它能让编译器警告,是因为编译器对它进行了语义分析。那么我可以继承它自己也写一个特性让编译出错吗?你再仔细看下ObsoleteAttribute是不是有一个关键字sealed,这个关键字直接让你无法继承它。那么我们可以继承Attribute,在写下其他特性,就不要纠结这个了。

 

 

 

 

 

 自定义特性

//该特性适用于所有的类,而且是非继承的。
    [AttributeUsage(AttributeTargets.Class, Inherited = false)]
    class OldAttribute : Attribute
    {
        private string discretion;

        public string Discretion
        {
            get { return discretion; }
            set { discretion = value; }
        }
        public DateTime date;
        public OldAttribute(string discretion)
        {
            this.discretion = discretion;
            date = DateTime.Now;
        }
    }
    [Old("我是一个特性")]
    public class SampleClass
    {
        public SampleClass()
        {
            Console.WriteLine("1111");
        }
    }

 

 

 

 public class NewClass : SampleClass
 {
        public void NewTest()
        {
            Console.WriteLine("222");
        }
 }

 

好了写到这里就写完了,是不是就大功告成了呢?当然不是了,想要使用它,我们还必须用反射去获取这个特性里面的属性值。mvc框架里面之所以拿来直接用,那是因为它框架里为你处理了这些过程。

        public static void GetAttributeInfo(Type t)
        {
            //检索自定义属性
            OldAttribute old = (OldAttribute)Attribute.GetCustomAttribute(t, typeof(OldAttribute));
            if (old == null)
            {
                Console.WriteLine(t.ToString() + "类中自定义特性不存在");
            }
            else
            {
                Console.WriteLine("特性描述:{0}\n加入事件时间:{1}", old.Discretion, old.date);
            }
        }

调用:

      static void Main(string[] args)
      {
            GetAttributeInfo(typeof(SampleClass));
            Console.WriteLine("=================");
            GetAttributeInfo(typeof(NewClass));
       }

结果:

 

 

我们在写一个:

public class TableNameAttribute : Attribute
    {
        public TableNameAttribute() { }

        public string TableName { get; set; }
    }

 然后我们放到创建的User类上:

 [TableName(TableName = "Users")]
    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

调用:

        /// <summary>
        /// 为类或成员添加描述信息,然后在使用的时候拿到该信息。
        /// </summary>
        public static void TableShow()
        {
            Type type = typeof(User);
            object[] obj = type.GetCustomAttributes(true);
            for (int i = 0; i < obj.Length; i++)
            {
                if (obj[i] is TableNameAttribute)
                {
                    TableNameAttribute tnAttr = (TableNameAttribute)obj[i];
                    Console.WriteLine(tnAttr.TableName);
                }
            }
        }

结果:

 

我们再试试下在枚举中使用特性:

 /// <summary>
    /// 备注特性
    /// </summary>
    public class RemarkAttribute : Attribute
    {
        private string Remark { get; set; }
        public RemarkAttribute(string _remark)
        {
            this.Remark = _remark;
        }
        public string GetRemark()
        {
            return this.Remark;
        }
    }
   public enum Sex
    {
        [Remark("男的")]
        boy = 1,
        [Remark("女的")]
        girl = 2
    }

调用:

/// <summary>
    /// 备注属性
    /// </summary>
    public static class EnumExtension
    {
        public static string GetRemake(Enum model)
        {
            if (model is Sex)
            {
                Type t = typeof(Sex);
                FieldInfo fi = t.GetField(model.ToString());
                object[] o = fi.GetCustomAttributes(true);
                foreach (var attr in o)
                {
                    if (attr is RemarkAttribute)
                    {
                        RemarkAttribute remark = (RemarkAttribute)attr;
                        return remark.GetRemark();
                    }
                }
            }
            return string.Empty;
        }
    }
EnumExtension.GetRemake(Sex.boy)

 

 

我们在看看验证一个类型范围:

 /// <summary>
    /// 验证范围
    /// </summary>
    public class IntValidateAttribute : Attribute
    {
        /// <summary>
        /// 最小值
        /// </summary>
        private int minValue { get; set; }
        /// <summary>
        /// 最大值
        /// </summary>
        private int maxValue { get; set; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        public IntValidateAttribute(int minValue, int maxValue)
        {
            this.minValue = minValue;
            this.maxValue = maxValue;
        }
        /// <summary>
        /// 检验值是否合法
        /// </summary>
        /// <param name="checkValue"></param>
        /// <returns></returns>
        public bool Validate(int checkValue)
        {
            return checkValue >= minValue && checkValue <= maxValue;
        }
    }

 

 public class User
    {
        [IntValidate(1, 10)]
        public int Id { get; set; }
        public string Name { get; set; }
    }

 

 public class BaseDal
    {
        public static string Insert<T>(T model)
        {
            Type type = typeof(T);
            //反射该类型的所有属性
            PropertyInfo[] infos = type.GetProperties();
            bool boIsCheck = true;
            foreach (var item in infos)
            {
                //找寻所有的特性的
                object[] o = item.GetCustomAttributes(true);
                if (item.PropertyType.Name.ToLower().Contains("int"))
                {
                    foreach (var attr in o)
                    {
                        IntValidateAttribute intValidate = (IntValidateAttribute)attr;
                        //执行特性的验证逻辑
                        boIsCheck = intValidate.Validate((int)item.GetValue(model));
                    }
                }
                if (!boIsCheck)
                {
                    break;
                }
            }
            if (boIsCheck)
            {
                return "验证通过,插入数据库成功";
            }
            else
            {
                throw new Exception("验证失败");
            }
        }
    }

调用:

只要我们这个ID的范围在1-10以内就符合,否则就报错。

string msg = BaseDal.Insert<User>(new User() { Id = 2, Name = "zero219" });

 

结果:

 

posted @ 2020-05-30 21:25  zero219  阅读(275)  评论(0编辑  收藏  举报