一、概述
Attribute说白了就是一个类而已,里边一般含有一些附加信息,或者一些特殊的处理逻辑,以便告诉编译器应用该特性的东东是个奇葩,需要特殊对待!
二、使用时的注意事项
2.1. Attribute是一个类,必须继承自System.Attribute
2.2 Attribute命名规范
Attribute命名一般以Attribute结尾, 但是在具体使用时候,可以省去Attribute这一后缀。加入定义了一个HelperAttribute, 具体使用的时候,可以这样写[Helper].
2.3 Attribute的使用限制
Attribute类在定义的时候,可以指定这个Attribute的应用范围,AttributeTargets枚举就列出了可以指定的范围,可以是class, field等;AllowMutiple为true或者false,意思就是是否让该特性在某个地方重复使用(比如在某一个类上使用多次);Inherited为true或者false,意思就是该特性是否会被应用该特性的类的子类继承。
2.4 Attribute中的参数赋值
位置参数(Attribute构造函数的参数):必填,且顺序要一致!
命名参数(Attribute中的其他字段或者属性):在使用时可以省略!
三、自定义一个Attribute并读取其值
举个栗子:
[AttributeUsage(AttributeTargets.Class, AllowMutiple=true, Inherited=false)]
public class BookAttribute:Attribute
{
public string Msg { get; set; }
public double Version = 1.0;
public MyFirstAttribute(string msg)
{
Msg= msg;
}
}
通过反射获取Attribute相关信息:
namespace TestAttribute {
//多次使用特性类
[Book("人民邮电")] [Book("北京")] class BookInfo { public string bookinfo = "图书信息"; //构造函数 public BookInfo() { } } }
static void Main(string[] args) { BookInfo bookinfo = new BookInfo(); MemberInfo typeinfo = typeof(BookInfo); object[] bookarr= typeinfo.GetCustomAttributes(typeof(BookAttribute), false); if (bookarr.GetLength(0) != 0) { BookAttribute bookattribute1 = (BookAttribute)bookarr[0]; BookAttribute bookattribute2 = (BookAttribute)bookarr[1]; Console.WriteLine(bookinfo.bookinfo); Console.WriteLine("出版社为:" + bookattribute1.Msg+ "城市为:" + bookattribute2.Msg); Console.ReadKey(); } }
四、学会使用一些.NET内置特性
举个栗子:
System.ObsoleteAttribute:告诉编译器某个方法已经过时,然后当编译器发现程序中有地方在使用这个用Obsolete标记过的方法时,就会给出一个警告信息。
public class TestClass
{
// 添加Obsolete特性
[Obsolete("请使用新的SendMsg(Message msg)重载方法")]
public static void ShowMsg()
{
Console.WriteLine("这是旧的SendMsg()方法");
}
}
private void button1_Click(object sender, EventArgs e)
{
TestClass.ShowMsg();
}
现在运行这段代码,我们会发现编译器给出了一个警告!
五、特性在枚举上的应用
enum Gender { [Description(“男”)] Man, [Description(“女”)] Woman };
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace MyTools { /// <summary> /// 枚举帮助类 /// </summary> public static class EnumHelper { /// <summary> /// 获取枚举项的Attribute /// </summary> /// <typeparam name="T">自定义的Attribute</typeparam> /// <param name="source">枚举</param> /// <returns>返回枚举,否则返回null</returns> public static T GetCustomAttribute<T>(Enum source) where T : Attribute { Type sourceType = source.GetType(); string sourceName = Enum.GetName(sourceType, source); FieldInfo field = sourceType.GetField(sourceName); object[] attributes = field.GetCustomAttributes(typeof(T), false); foreach (object attribute in attributes) { if (attribute is T) return (T)attribute; } return null; } /// <summary> ///获取DescriptionAttribute描述 /// </summary> /// <param name="source">枚举</param> /// <returns>有description标记,返回标记描述,否则返回null</returns> public static string GetDescription(this Enum source) { var attr = GetCustomAttribute<System.ComponentModel.DescriptionAttribute>(source); if (attr == null) return null; return attr.Description; } public static EnumT GetValueByDescription<EnumT>(string description) { var type = typeof(EnumT); if (!type.IsEnum) throw new ArgumentException("This method is destinated for enum types only."); foreach (var enumName in Enum.GetNames(type)) { var enumValue = Enum.Parse(type, enumName); if (description == ((Enum)enumValue).GetDescription()) return (EnumType)enumValue; } throw new ArgumentException("There is no value with this description among specified enum type values."); } } }
使用方法:
Gender.Man.GetDescription()
注意MVC中特性的巧妙应用,改写!