特 征
特征(Attribute)是C#为组件编程引入的一个令人兴奋的创新,它使得我们可以为程序的各种元素如类、结构、接口、方法等提供额外的描述性信息,这些描述性信息在程序代码运行时可以被提取利用。看下面一个示例程序:
using System;
public class AuthorAttribute: Attribute {
//作者特征类
public AuthorAttribute(string name) {
this.name = name;}
public string Name { get { return name; } }
private string name;
}
[Author(“Anders Hejlsberg”)]//特征实例化
class MyClass {
int count;
public MyClass(int count) {
this.count=count;}
public int Count {
get{ return count;}}
}
class Test {
static void Main() {
Type t1=typeof(MyClass);
Type t2=typeof(AuthorAttribute);
object[] arr=t1.GetCustomAttributes(t2,true);
//获取特征实例(数组)
Console.Write(“The author of MyClass is :”);
foreach(object o in arr) {
AuthorAttribute aa=(AuthorAttribute) o;
Console.Write(“{0}”, aa.Name);
}
Console.WriteLine();
}
}
程序首先声明并实现了一个AuthorAttribute特征类,特征类必须直接或间接继承自抽象类System.Attribute,这往往是使用特征时的第一步,它将提供描述性信息的数据结构。值得指出的是AuthorAttribut特征类名中的后缀“Attribute”是C#推荐的特征类命名方式,并非必须如此。
上例中在实现类MyClass的时候,采用AuthorAttribute
特征类来为MyClass提供描述信息。特征实例化语句Author(“Anders Hejlsberg”)帮助完成这一行为,这里的括号“[ ]”告诉C#在进行特征实例化。Author是AuthorAttribute类去掉后缀“Attribute”的简写形式——C#编译器可以自动识别,当然我们将Author换成AuthorAttribute后效果是一样的,其中(“Anders Hejlsberg”)将调用AuthorAttribute特征类的AuthorAttribute(string name) 实例构造器。通过这样的特征实例化语句后,就给MyClass类提供了一个“撰写者”(AuthorAttribute)的特征描述。在Test测试类中,我们便可以通过映射来获得我们先前设定的描述信息。运行程序可以得到下面的结果:The author of MyClass is : Anders Hejlsberg。
参 数
特征实例化时有两种参数,一种如前面由特征类的实例构造器定义的参数,称为“位置参数”。另一种是由特征类中定义的实例公有域或实例属性赋值的参数,称为“指定参数”。看下面特征类的实现:
public class HelpAttribute: Attribute{
public HelpAttribute(string url) {
this.url = url;}
public string Topic = null;
private string url;
private int number=-1;
public string Url {
get { return url; }}
public int Number{
get{ return number; }
set{ number=value;}
}
}
对如上一个特征类的实例化,往往采用下面的语句: Help(“http://www.ccw.com.cn”,Topic=“A demo class”,Number=120)。其中“http://www.ccw.com.cn”是位置参数; 而Topic=“A demo class”是指定参数,对应HelpAttribute类中的Topic公有域; “Number=120”也是指定参数,对应HelpAttribute类中的Number公有属性。
位置参数和相应特征类的实例构造器紧密相关——构造器提供了什么样的参数构造方式,位置参数就对应什么样的形式。位置参数不可省略,但如果特征类提供了无参数的构造器,那就另当别论。指定参数对应着特征类的实例公有域或实例属性,但它在实例化的时候并非必须,可以省略。
位置参数和指定参数对它们的数据类型也有要求,这主要是保证在括号“[ ]”实例化语句中能完成各个参数的初始化。它们必须是下列类型之一:八种整数类型sbyte, short, int, long,byte, ushort, uint和ulong;字符类型char和布尔类型bool;两种浮点类型float 和double;System.Object(即object)和System.Type(typeof操作符返回值);枚举类型。
AttributeUsage特征类
AttributeUsage特征类是C#保留的三个特征类之一(其他两个是条件特征类ConditionalAttribute和废弃特征类ObsoleteAttribute)。AttributeUsage特征类用来描述自己实现的特征类怎样描述其他类,比如我们实现的特征是用于描述方法,还是类、接口?是否允许特征类对同一个编程元素进行多次描述(比如一个类的撰写者可能有多个)?一个类在被特征类描述后,这种描述是否能够体现在它的继承子类上?AttributeUsage特征类通过三个属性来体现上述的行为: ValidOn,AllowMultiple,Inherited。
需要指出的是AttributeUsage特征类只能够用于直接或间接继承自System.Attribute类,否则编译器会报错。
下面的例子演示了AttributeUsage特征类的典型用法:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AuthorAttribute: Attribute {
public AuthorAttribute(string name) {
this.name = name; }
public string Name {
get {return name; } }
private string name;
}
以上指定了AuthorAttribute特征类只能用于描述类(AttributeTargets.Class),并且它允许用多个AuthorAttribute特征类来描述同一个编程元素(AllowMultiple = true)。这里并没有指定Inherited的值,它默认为真(true),也就是允许继承子类获得父类的描述。
被AttributeUsage描述的特征类,必须严格按照指定的描述信息去描述其他编程元素,否则会引起编译器报错!
条件特征类ConditionalAttribute定义在某些条件下才能够产生调用的类。废弃特征类ObsoleteAttribute顾名思义是指在某些情况下不推荐使用旧的被废弃的类型或方法等编程元素,这时在它的前面加上废弃特征类从而可以通知编译器,编译器编译时往往会给出警告信息。
特征(Attribute)是C#为组件编程引入的一个令人兴奋的创新,它使得我们可以为程序的各种元素如类、结构、接口、方法等提供额外的描述性信息,这些描述性信息在程序代码运行时可以被提取利用。看下面一个示例程序:
using System;
public class AuthorAttribute: Attribute {
//作者特征类
public AuthorAttribute(string name) {
this.name = name;}
public string Name { get { return name; } }
private string name;
}
[Author(“Anders Hejlsberg”)]//特征实例化
class MyClass {
int count;
public MyClass(int count) {
this.count=count;}
public int Count {
get{ return count;}}
}
class Test {
static void Main() {
Type t1=typeof(MyClass);
Type t2=typeof(AuthorAttribute);
object[] arr=t1.GetCustomAttributes(t2,true);
//获取特征实例(数组)
Console.Write(“The author of MyClass is :”);
foreach(object o in arr) {
AuthorAttribute aa=(AuthorAttribute) o;
Console.Write(“{0}”, aa.Name);
}
Console.WriteLine();
}
}
程序首先声明并实现了一个AuthorAttribute特征类,特征类必须直接或间接继承自抽象类System.Attribute,这往往是使用特征时的第一步,它将提供描述性信息的数据结构。值得指出的是AuthorAttribut特征类名中的后缀“Attribute”是C#推荐的特征类命名方式,并非必须如此。
上例中在实现类MyClass的时候,采用AuthorAttribute
特征类来为MyClass提供描述信息。特征实例化语句Author(“Anders Hejlsberg”)帮助完成这一行为,这里的括号“[ ]”告诉C#在进行特征实例化。Author是AuthorAttribute类去掉后缀“Attribute”的简写形式——C#编译器可以自动识别,当然我们将Author换成AuthorAttribute后效果是一样的,其中(“Anders Hejlsberg”)将调用AuthorAttribute特征类的AuthorAttribute(string name) 实例构造器。通过这样的特征实例化语句后,就给MyClass类提供了一个“撰写者”(AuthorAttribute)的特征描述。在Test测试类中,我们便可以通过映射来获得我们先前设定的描述信息。运行程序可以得到下面的结果:The author of MyClass is : Anders Hejlsberg。
参 数
特征实例化时有两种参数,一种如前面由特征类的实例构造器定义的参数,称为“位置参数”。另一种是由特征类中定义的实例公有域或实例属性赋值的参数,称为“指定参数”。看下面特征类的实现:
public class HelpAttribute: Attribute{
public HelpAttribute(string url) {
this.url = url;}
public string Topic = null;
private string url;
private int number=-1;
public string Url {
get { return url; }}
public int Number{
get{ return number; }
set{ number=value;}
}
}
对如上一个特征类的实例化,往往采用下面的语句: Help(“http://www.ccw.com.cn”,Topic=“A demo class”,Number=120)。其中“http://www.ccw.com.cn”是位置参数; 而Topic=“A demo class”是指定参数,对应HelpAttribute类中的Topic公有域; “Number=120”也是指定参数,对应HelpAttribute类中的Number公有属性。
位置参数和相应特征类的实例构造器紧密相关——构造器提供了什么样的参数构造方式,位置参数就对应什么样的形式。位置参数不可省略,但如果特征类提供了无参数的构造器,那就另当别论。指定参数对应着特征类的实例公有域或实例属性,但它在实例化的时候并非必须,可以省略。
位置参数和指定参数对它们的数据类型也有要求,这主要是保证在括号“[ ]”实例化语句中能完成各个参数的初始化。它们必须是下列类型之一:八种整数类型sbyte, short, int, long,byte, ushort, uint和ulong;字符类型char和布尔类型bool;两种浮点类型float 和double;System.Object(即object)和System.Type(typeof操作符返回值);枚举类型。
AttributeUsage特征类
AttributeUsage特征类是C#保留的三个特征类之一(其他两个是条件特征类ConditionalAttribute和废弃特征类ObsoleteAttribute)。AttributeUsage特征类用来描述自己实现的特征类怎样描述其他类,比如我们实现的特征是用于描述方法,还是类、接口?是否允许特征类对同一个编程元素进行多次描述(比如一个类的撰写者可能有多个)?一个类在被特征类描述后,这种描述是否能够体现在它的继承子类上?AttributeUsage特征类通过三个属性来体现上述的行为: ValidOn,AllowMultiple,Inherited。
需要指出的是AttributeUsage特征类只能够用于直接或间接继承自System.Attribute类,否则编译器会报错。
下面的例子演示了AttributeUsage特征类的典型用法:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AuthorAttribute: Attribute {
public AuthorAttribute(string name) {
this.name = name; }
public string Name {
get {return name; } }
private string name;
}
以上指定了AuthorAttribute特征类只能用于描述类(AttributeTargets.Class),并且它允许用多个AuthorAttribute特征类来描述同一个编程元素(AllowMultiple = true)。这里并没有指定Inherited的值,它默认为真(true),也就是允许继承子类获得父类的描述。
被AttributeUsage描述的特征类,必须严格按照指定的描述信息去描述其他编程元素,否则会引起编译器报错!
条件特征类ConditionalAttribute定义在某些条件下才能够产生调用的类。废弃特征类ObsoleteAttribute顾名思义是指在某些情况下不推荐使用旧的被废弃的类型或方法等编程元素,这时在它的前面加上废弃特征类从而可以通知编译器,编译器编译时往往会给出警告信息。