对类来说:属性成员描述的是状态信息,对类的实例来说,属性成员的值表示的是该对象的状态值。
1、如果类Z是抽象的,包含它的类A 也应该是抽象的。
2、重写属性的声明必须与指定与所继承的属性相同的修饰符,类型等
3、如果被继承的属性只有单个访问器(读或者写),重写属性也只能单个访问器。如果被继承的属性有两个访问器,重写属性可以只包含一个,也可包含两个
4、重写属性可以包含seal修饰符,此修饰符可以防止派生类重写该属性
为实体类型(类、接口、方法、属性)描述附加信息的方法。一旦代码的实体被附加了信息,就可以在运行时获得这些信息。特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。
Attribute本质上就是一个类,派生于System.Attribute类。它附着在目标对象上最终实例化
1、 定义Attribute类
2、 使用Attribute类
3、 查询Attribute类
使用格式:放在[ ]即可
[显示说明符:特征列表]
也可以使用带参数的Attribute类 :[Attribute类名(位置参数表,命名参数表)]
位置参数表:即构造函数的参数
命名参数表:Attribute实例中的属性的赋值
查询代码实体成员上的特征信息,AttributeUsage有三个属性,我们可以把它放置在定制属性前面。
第一个属性:ValidOn,通过这个属性,我们能够定义定制特性应该在何种程序实体前放置
第二个属性: AllowMultiple ,这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次
第三个属性是: Inherited ,我们可以使用这个属性来控制定制特性的继承规则。它标记了当特性被放置在一个基类上时,它能否被派生类所继承。
例子:
//自定义Attribute类
// This attribute is only valid on a class.
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method),
AllowMultiple=true,
Inherit=false]
public class ClassTargetAttribute : Attribute {
}
// This attribute is only valid on a method.
[AttributeUsage(AttributeTargets.Method)]
public class MethodTargetAttribute : Attribute {
}
// This attribute is only valid on a constructor.
[AttributeUsage(AttributeTargets.Constructor)]
public class ConstructorTargetAttribute : Attribute {
}
// This attribute is only valid on a field.
[AttributeUsage(AttributeTargets.Field)]
public class FieldTargetAttribute : Attribute {
}
// This attribute is valid on a class or a method.
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
public class ClassMethodTargetAttribute : Attribute {
}
// This attribute is valid on a generic type parameter.
[AttributeUsage(AttributeTargets.GenericParameter)]
public class GenericParameterTargetAttribute : Attribute {
}
[ClassTarget]//系统会自动添加Attribute
[ClassMethodTarget]//系统会自动添加Attribute
[AllTargets]
public class TestClassAttribute {
[ConstructorTarget]
[AllTargets]
TestClassAttribute() {
}
[MethodTarget]
[ClassMethodTarget]
[AllTargets]
public void Method1() {
}
[FieldTarget]
[AllTargets]
public int myInt;
// This attribute is valid on any target.
[AttributeUsage(AttributeTargets.All)]
public class AllTargetsAttribute : Attribute {
}
注意:对一个特性类名使用Attribute后缀是一个惯例,也可不添加,系统会自动添加。
Attribute类的查询
1、使用GetCustomAttribute或者GetCustomAttributes方法查询,查询指定代码实体上指定特征类型
2、使用反射机制查询
第一个例子,我们通过特性类Attribute,来对类、以及类成员进行进一步的描述。
比如我们写一个关于人的类Person,该类可以对人的属性以及某些行为(方法)进行描述。那么如果我们要对人类进行进一步描述呢,比如人这个类是属于动物的灵长类动物。有人会说我们可以为这个Person类去写一个灵长动物类的父类,再用人类去继承这个类去解决。但是我们要求的是仅仅是描述性的,就是对这个人类进行进一步的描述,而在实际操作中不需要去操作。这样的情况我们就可以用特性的概念去解决,特性简而言之就是程序集的特定程序元素所具有的另外的性质。
我们先写一个人类Person类
Class Person
{
//人的姓名储存字段和属性
private string name;
public string Name
{
set{name=value;}
get{return name;}
//人的年龄储存字段和属性
private int age;
public int Age
{
set{age=value;}
get{return age;}
}
}
//人的打招呼方法
public void SayHello()
{
Console.WriteLine("大家好,我叫{0},我今年{1}岁了,我的性别是{2}",this.Name,this.Age,this.Sex);
}
}
然后写动物的特性类AnimalAttribute类继承于Attribute(特性)
class AnimalAttribute:Attribute
{
//字段和属性描述是否是灵长类
private bool isPrimate;
public bool IsPrimate
{
set { isPrimate = value; }
get { return isPrimate; }
}
}
然后对人类进行动物类描述。即在人类的定义前面加:
[Animal(IsPrimate=true)]//为人类加特性,指定人类是灵长类。
下面我们就可以通过代码来获得人类的特性:
//声明特性对象,并通过Attribute类的静态方法GetCustomAttribute()获得人类的在动物类的特性,并赋值给特性对象
Attribute att1 = Attribute.GetCustomAttribute(typeof(Person), typeof(AnimalAttribute));
//将特性对象转化为动物特性对象
AnimalAttribute animalAtt = att1 as AnimalAttribute;
//检查转化是否成功如果成功则打印这个特性对象的是否是灵长类的属性。
if (animalAtt != null)
{
Console.WriteLine("人类是否是灵长类:{0}",animalAtt.IsPrimate);
}
Console.ReadKey();
第二个例子,类似,给不同的方法添加不同的Animal的类型
// An enumeration of animals. Start at 1 (0 = uninitialized).
public enum Animal
{
// Pets.
Dog = 1,
Cat,
Bird,
}
// A custom attribute to allow a target to have a pet.
public class AnimalTypeAttribute : Attribute
{
// The constructor is called when the attribute is set.
public AnimalTypeAttribute(Animal pet)
{
thePet = pet;
}
// Keep a variable internally ...
protected Animal thePet;
// .. and show a copy to the outside world.
public Animal Pet
{
get { return thePet; }
set { thePet = value; }
}
}
// A test class where each method has its own pet.
class AnimalTypeTestClass
{
[AnimalType(Animal.Dog)]
public void DogMethod() { }
[AnimalType(Animal.Cat)]
public void CatMethod() { }
[AnimalType(Animal.Bird)]
public void BirdMethod() { }
}
class DemoClass
{
static void Main(string[] args)
{
AnimalTypeTestClass testClass = new AnimalTypeTestClass();
Type type = testClass.GetType();
// Iterate through all the methods of the class.
foreach (MethodInfo mInfo in type.GetMethods())
{
// Iterate through all the Attributes for each method.
foreach (Attribute attr in
Attribute.GetCustomAttributes(mInfo))
{
// Check for the AnimalType attribute.
if (attr.GetType() == typeof(AnimalTypeAttribute))
Console.WriteLine(
"Method {0} has a pet {1} attribute.",
mInfo.Name, ((AnimalTypeAttribute)attr).Pet);
}
}
Console.ReadKey();
}
}
/*
* 输出:
* Method DogMethod has a pet Dog attribute.
* Method CatMethod has a pet Cat attribute.
* Method BirdMethod has a pet Bird attribute.
*/