C#语法小知识(七)特性
来源:互联网 发布:华盛顿城市道路网络 编辑:程序博客网 时间:2024/04/30 10:43
特性(Attribute)提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。
特性具有以下属性:特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的 .NET 程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员。
可以添加自定义特性,以指定所需的任何附加信息。
可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。
特性可以与方法和属性相同的方式接受参数。
程序可以使用反射检查自己的元数据或其他程序内的元数据。
本文就实现一个简单的自定义特性作为示例:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]public class TestAttribute: Attribute{public int val{ get; private set;}public TestAttribute(int i){val = i;}}我们为TestAttribute添加了特性AttributeUsage,表明它只可以被添加到类(class)、方法(Method)和属性(Property)上。
所有的特性都继承自System.Attribute。
TestAttribute的构造函数便是它接收参数的地方(参数数量不限)。
添加自定义特性:
[Test(0)]class Test0{[Test(1)]public void Test1() {}[Test(2)]public int Test2 {get;set;}}
我们为Test0这个类和它的成员方法Test1以及成员属性Test2分别添加了三个参数不一样的Test特性。如果我们想为成员变量添加一个Test特性:
[Test(3)]public int Test3;
就无法编译通过,需要为TestAttribute的AttributeUsage特性修改参数:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field)]我们知道了如何创建自定义特性,知道了如何使用自定义特性,但是不知道如何访问自定义特性也并没有什么
我们需要使用System.Reflection(反射)来访问自定义特性。
Test0 tmp = new Test0 ();Type t = tmp.GetType ();foreach (Attribute attr in t.GetCustomAttributes(true)) {if (attr is TestAttribute) {Console.WriteLine (((TestAttribute)attr).val);}}foreach (var m in t.GetMethods()) {foreach (Attribute attr in m.GetCustomAttributes(true)) {if (attr is TestAttribute) {Console.WriteLine (((TestAttribute)attr).val);}}}foreach (var p in t.GetProperties()) {foreach (Attribute attr in p.GetCustomAttributes(true)) {if (attr is TestAttribute) {Console.WriteLine (((TestAttribute)attr).val);}}}
或者
MethodInfo mi = t.GetMethod ("Test2");foreach (Attribute attr in mi.GetCustomAttributes(true)) {if (attr is TestAttribute) {Console.WriteLine (((TestAttribute)attr).val);}}PropertyInfo pi = t.GetProperty ("Test3");foreach (Attribute attr in pi.GetCustomAttributes(true)) {if (attr is TestAttribute) {Console.WriteLine (((TestAttribute)attr).val);}}或许你还不了解什么情况下需要使用自定义属性,Unity3D的SerializeField和ExecuteInEditMode就是很好的例子。
如果你不了解Unity3D也没关系,这里可以简单解释一下。
例如:你的代码需要将对象保存为文件,这就需要序列化成员变量,但是有些变量需要序列化,而有些并不需要,你就可以添加一个自定义特性(例如SerializeFieldAttribute)来标识这些成员变量,在序列化的时候,判断所有成员变量是否有这个特性,有的才被序列化。
再例如:你的程序有不同的两种模式Edit和Play,有些成员方法需要在Edit模式下运行,有些并不需要,你就可以添加一个自定特性(例如ExecuteInEditModeAttribute)来标识这些成员方法,在Edit模式下在调用这个方法是之前,判断这个方法是否有这个特性,有这个特性才会被调用。或者有些成员方法并不需要在Play下运行,你就可以定义一个带参数的特性,用于区分不同的模式。
附上特性的作用范围:
1 0
- C#语法小知识(七)特性
- C#语法小知识(八)扩展
- C#语法小知识(九)事件
- C#语法小知识(十)反射
- C#语法小知识(十一)泛型
- C#语法小知识(十九)using
- C#语法造成的小问题(编译原理知识)
- C#语法小知识(三)枚举类型enum
- C#语法小知识(四)委托delegate
- C#语法小知识(五)接口interface
- C#语法小知识(六)属性与索引器
- C#语法小知识(十五)异常处理
- C#语法小知识(十八)const与readonly
- C#语法小知识(二十)params
- C#语法小知识(二十一)ref与out
- C#语法小知识(二十二)集合Collection
- C#语法小知识(二十三)重载运算符
- C#语法小知识(二十四)自定义类型转换
- iOS应用安全读书笔记之日历事件
- 言简意赅话死锁
- 【NOIP模拟】灌水
- 0061 strcpy strcmp strcat strlen memcpy函数再写
- 线程
- C#语法小知识(七)特性
- 数组常用函数
- android图片自动定时切换
- 二叉树,B树之类持续更新
- web编程要完成的几个功能
- 关于javascript的闭包和匿名函数
- JSON学习总结
- 时钟四:实现闹钟
- c++计算长方体周长和面积