C# 特性

120 阅读4分钟

介绍

特性(Attribute)是一种用于在程序运行时传递各种元素(例如类、方法、结构、枚举等)行为信息的声明性标签。使用特性可以将元数据(例如编译器指令、注释、描述、方法和类等信息)添加到程序中。

.Net Framework 提供了两种类型的特性,分别是预定义特性和自定义特性

特性具有以下属性:

  • 使用特性可以向程序中添加元数据;
  • 可以将一个或多个特性应用于整个程序、模块或者较小的程序元素(例如类和属性)中;
  • 特性可以像方法和属性一样接受自变量;
  • 程序可使用反射来检查自己的元数据或其他程序中的元数据。

语法

在要应用特性的元素前面用方括号[]来应用。如[Table("tableName")]

[特性名(指定信息参数)]
[Table("studentInfos")]
public class studentInfo
{

}

预定义特性

Net Framework 中提供了三个预定义的属性:

  • AttributeUsage;
  • Conditional;
  • obsolete.

AttributeUsage

预定义特性 AttributeUsage 用来描述如何使用自定义特性类,用于自定义特性类前面,规定了特性可应用到的项目的类型。

格式如下:

[Attributeusage(
    validon,
    AllowMultiple = allowmultiple,
    Inherited = inherited
)]

参数说明如下:

  • 参数validon 用来定义特性可被放置的程序元素。它是枚举器 AttributeTargets 的值的组合。默认值是AttributeTargets.All;
  • 参数 allowmultiple(可选参数)用来为该特性的 AowMulipl!e属性(property)提供一个布尔值,默认值为false(单用的),如。果为 true,则该特性是多用的;
  • 参数inherited(可选参数)用来为该特性的Inherited属性(property)提供一个布尔值,默认为false(不被继承),如果为 true,则该特性可被派生类继承。

Conditional

预定义特性 Conditional 用来标记一个方法,它的执行依赖于指定的预处理标识符。根据该特性值的不同,在编译时会起到不同的效果

[Conditional("out")]
public void Print(string msg)
{
    Console.writeLine(msg);
}

如果没有定义这个,就会忽略该方法。

obsolete

预定义特性 Obsolete 用来标记不应被使用的程序,您可以使用它来通知编译器放弃某个目标元素。

语法:[obsolete(message,iserror)]
[obsolete("Printout 已用",false)]
public void Printout(string msg)
{
    Console.writeLine("输出消息:"+msg);
}

语法说明如下:

  • 参数 message 是一个字符串,用来描述项目为什么过时以及应该使用什么替代;
  • 参数 iserror是一个布尔值,默认值是false(编译器会生成一个警告),如果设置为true,那么编译器会把该项目的当作一个错误。

自定义特性

.Net Framework 允许创建自定义特性,自定义特性不但用于存储声明性的信息,还可以在运行时被检索。创建并使用自定义特性可以分为四个步骤:

  • 声明自定义特性——特性名一般规定以Attribute结尾,派生于System.Attribute类;
  • 构建自定义特性——定义属性或字段,创建构造函数、指定应用目标;
  • 在目标程序上应用自定义特性——[特性名(参数值)];
  • 通过反射访问特性。

最后一步涉及编写一个简单的程序来读取元数据以便查找各种符号。该程序应在运行时使用反射来访问特性

声明自定义特性

自定义特性应该继承 System.Attribute 类

public class RemarkAttribute:Attribute
{

}

构建自定义特性

给RemarkAttribute类定义属性或字段、构造函数,并指定应用目标。

[AttributeUsage(AttributeTargets.Class |  
 AttributeTargets.Constructor |  
 AttributeTargets.Field |  
 AttributeTargets.Method |  
 AttributeTargets.Property,  
 AllowMultiple = true)]
public class RemarkAttribute:Attribute
{
    public string description { get;set;}
    public RemarkAttribute(string desp)
    {
        Description =desp;
    }
}

应用自定义特性

通过把特性放置在紧挨着它的目标上面来应用该特性。

[Remark("名目信息")]
public class ItemInfo
{
    [Remark("编号")]
    public int ItemNo {get;set;}
    [Remark("名称")]
    public string ItemName { get; set;}
    [Remark("类别")]
    public ItemTypes ItemType {get;set;}
    
}

通过方法访问特性

在程序中,用反射的方式获取应用元素之上的特性标注的特性信息。

在AttributeHelper类中

//获取应用于类的注释信息
public static string GetclassDescription<T>()
{
    string desp=nu1l;
    Type type =typeof(T);
    //获取应用在类上的Remark特性对象
    RemarkAttribute attr =type.GetCustomAttribute<RemarkAttribute>();
    if(attr != null])
    {
        desp = attr.Description;
        return desp;
    //获取应用于属性的注释信息
    public static string GetPropertyDescription(this PropertyInfo p)
    {
        string desp=null;
        //获取应用在属性上的Remark特性对象
        RemarkAttribute attr =p.GetcustomAttribute<RemarkAttribute>();
        if (attr != null)
        {
            desp = attr.Description
        }
        return desp;
    }
    //获取类和属性的注释
    ItemInfo itemInfo01 = new ItemInfo()
    {
        ItemNo = no,
        ItemName = itemName,
        ItemType =itemType
    }
    //获取ItemInfo的注释
    string itemRemark=AttributeHelper.GetclassDescription<ItemInfo>();
    Type type=typeof(ItemInfo);
    //获取各属性的注释
    string noRemark=type.GetProperty("ItemNo").GetPropertyDescription();
    string nameRemark=type.GetProperty("ItemName").GetPropertyDescription();
    string typeRemark=type.GetProperty("ItemType").GetPropertyDescription():