前言
特性,以 Atrribute 为关键字,声明一种特殊的类,用中括号 [] 括起来,附着在其他类或者方法或者成员上,为程序运行提供额外的信息。
特性可以分为 .Net 预定义特性和自定义特性。
一、预定义特性
预定义特性有很多,比如 Obsolete、Conditional、Discription 等。
Obsolete:
using System; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Update update = new Update(); update.Load(); Console.WriteLine(); Console.ReadKey(); } } [Obsolete("该类已过时,建议使用UpdateNew", true)] class Update { [Obsolete("该方法已过时,建议使用LoadNew", true)] public void Load() { } } }
编译根据 “Obsolete” 特性,禁止使用该类或该方法,写出来就报错。如果把 true 改为 false,则编译器仅提示,不报错,类和方法也正常调用。在大型、多人合作的项目中,使用 Obsolote 可以起到很好的版本控制。
Conditional
#define Debug //定义对应 Conditional 的宏 using System; using System.Diagnostics; namespace ConsoleApp1 { class Program { static void Main(string[] args) { Test(); Test2(); Console.WriteLine(); Console.ReadKey(); } [Conditional("Debug")] public static void Test() { Console.WriteLine("Conditional debug"); } public static void Test2() { #if Condition Console.WriteLine("Conditional2 debug"); #endif } } }
Test() 和 Test2() 表示了 Condition 的两种用法,当然是建议用特性的方式,这样做的好处是,我们可以控制调试信息是否打印,开发阶段定义一个和 Condition(string str) 参数一样的宏,相关方法就会执行。黑盒测试阶段可以注销掉宏,被相关 Condition 附着的类或者方法就不会执行。
Discription
using System; using System.ComponentModel; using System.Reflection; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string website = GetDescription(WebSite.网易云音乐); System.Diagnostics.Process.Start(website); Console.ReadKey(); } static string GetDescription(Enum enumValue) { string value = enumValue.ToString(); FieldInfo fieldInfo = enumValue.GetType().GetField(value); object[] objs = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if (objs == null || objs.Length == 0) { return value; } DescriptionAttribute descriptionAttribute = (DescriptionAttribute)objs[0]; return descriptionAttribute.Description; } } enum WebSite { [Description("https://music.163.com/")] 网易云音乐 = 0, [Description("https://www.bilibili.com/")] 哔哩哔哩 = 1, [Description("https://runner.ink/")] 个人博客 = 2 } }
使用 Description 特性给成员附加信息,在枚举里面很好用。
二、自定义特性
前面也说了,特性其实就是一个类,一个继承了 Atrribute 类的类。语法允许我们创建自己的特性,给其他类打标签。
using System; using System.Reflection; namespace ConsoleApp2 { class Program { static void Main(string[] args) { User user = new User(); //获取类型 Type type = typeof(User); //获取指定的特性(这个时候得到的是 Attribute 类,为基类) Attribute attribute = type.GetCustomAttribute(typeof(TableNameAtrribute), false); //基类转化成具体特性 TableNameAtrribute tableNameAtrribute = (TableNameAtrribute)attribute; //获取自定义特新的属性 Console.WriteLine(tableNameAtrribute.TableName); Console.ReadKey(); } } [TableNameAtrribute("users")] [Serializable] class User { public string Name { get; set; } public int Age { get; set; } public string Addr { get; set; } } class TableNameAtrribute : Attribute { public TableNameAtrribute(string tableName) { TableName = tableName; } public string TableName { get; set; } } }
上面的代码表明,可以给对象 “附着” 多个特性。[] 括号里的方法其实就是特性的构造函数。
后记
特性被用在很多地方,比如 IOC 注入和拦截器、特性三者结合,可以实现被拦截特性附着的类会被拦截的功效。
也会用来做数值校验等。