利用属性(Attribute)扩展元数据

本文深入介绍了C#中的Attribute,包括Attribute概述、应用方式、编写自定义属性以及如何检索存储在属性中的信息。通过示例展示了如何在方法和程序集级别应用属性,以及如何定义和获取属性的实例。同时,文章提到了AttributeUsageAttribute在控制属性应用范围中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Attribute 概述

 公共语言运行库允许您添加类似关键字的描述性声明(称为属性 (Attribute))来批注编程元素,如类型、字段、方法和属性 (Property)。

关键字:如果您使用过 C++,或许对包含关键字(如 public 和 private)的声明比较熟悉,这些关键字提供有关类成员的其他信息。另外,这些关键字通过描述类成员对其他类的可访问性来进一步定义类成员的行为。由于编译器被显式设计为识别预定义关键字,因此传统上您没有机会创建自己的关键字。


二、应用属性

通过下列过程将属性应用到代码元素。

    通过从 .NET Framework 导入属性的命名空间来定义新的属性或使用现有属性。

    通过在紧邻代码元素之前放置属性来将该属性应用于代码元素。

    为属性指定位置参数和命名参数。

属性在您编译代码时被发送到元数据中,并可通过运行库反射服务用于公共语言运行库以及任何自定义工具或应用程序。

 按照约定,所有属性名都以 Attribute 结尾。但是,某些以运行库为目标的语言(如 Visual Basic 和 C#)不要求指定属性的全名。例如,如果要初始化 System.ObsoleteAttribute,只需将其引用为 Obsolete 即可。

将属性应用于方法 
下面的代码示例显示如何声明 System.ObsoleteAttribute,该属性将代码标记为过时。字符串 "Will be removed in next version" 被传递到该属性。当调用该属性所描述的代码时,该属性将产生编译器警告以显示所传递的字符串。

  1.  using System;
  2.   public class Example
  3.   {
  4.       // Specify attributes between square brackets in C#.
  5.       // This attribute is applied only to the Add method.
  6.       [Obsolete("Will be removed in next version.")]
  7.       public static int Add(int a, int b)
  8.       {
  9.    return (a + b);
  10.       }
  11.   }
  12.   class Test
  13.   {
  14.       static void Main()
  15.       {
  16.    // This generates a compile-time warning.
  17.    int i = Example.Add(2, 2);
  18.       }
  19.   }

 

在程序集级别应用属性 
    如果要在程序集级别应用属性,请使用 Assembly 关键字。下列代码显示在程序集级别应用的 AssemblyNameAttribute。

  1.   using System.Reflection;
  2.   [assembly:AssemblyName("MyAssembly")]

三、编写自定义属性

自定义属性实质上是直接或间接地从 System.Attribute 派生的传统类。与传统类一样,自定义属性也包含存储和检索数据的方法。
正确设计自定义属性类的主要步骤如下:

    1、应用 AttributeUsageAttribute 
        自定义属性声明以 AttributeUsageAttribute 开始,包含三个对创建自定义属性具有重要意义的成员:AttributeTargets、Inherited 和 AllowMultiple。   
        AttributeTargets 成员:指示该属性可以应用的程序元素。以下之一:程序集、字段、事件、方法、模块、参数、属性、返回值、类型。

         继承属性:Inherited 属性:指示属性是否可由从该属性应用到的类派生的类继承。该属性采用 true(默认值)或 false 标志。   
         AllowMultiple 属性: 指示元素中是否可存在属性的多个实例。

    2、声明属性类 
         应用 AttributeUsageAttribute 后,可以开始定义属性细节。属性类的声明与传统类的声明类似,但需要注意一下几点:   
                       属性类必须声明为公共类。
                       按照约定,属性类的名称以单词 Attribute 结尾。虽然并不要求这样,但出于可读性目的,建议采用此约定。应用属性时,可以选择是否包含 Attribute 一词。
                       所有属性类都必须直接或间接地从 System.Attribute 继承。
                       在 Microsoft Visual Basic 中,所有自定义属性类都必须具有 AttributeUsageAttribute 属性。

    3、声明构造函数 
        用构造函数初始化属性的方法与对待传统类的方法相同。
    4、声明属性 
        如果需要定义命名参数,或者要提供一种容易的方法来返回由属性存储的值,请声明属性。应将属性 (Attribute) 的属性 (Property) 声明为带有要返回的数据类型说明的公共实体。定义将保存属性值的变量,并将该变量与 get 方法和 set 方法关联。
          示例代码:

  1. [AttributeUsage(AttributeTargets.All)]
  2. public class DeveloperAttribute : System.Attribute 
  3. {
  4.         
  5.     //Private fields.
  6.     private string name;
  7.     private string level;
  8.     private bool reviewed;
  9.     //This constructor defines two required parameters: name and level.
  10.     public  DeveloperAttribute(string name,string level)
  11.     {
  12.         this.name = name;
  13.         this.level = level; 
  14.         this.reviewed = false;
  15.     }
  16.     //Define Name property.
  17.     //This is a read-only attribute.
  18.         
  19.     public virtual string Name
  20.     {
  21.         get {return name;}        
  22.     }
  23.     //Define Level property.
  24.     //This is a read-only attribute.
  25.         
  26.     public virtual string Level
  27.     {
  28.         get {return level;}
  29.     }
  30.     //Define Reviewed property. 
  31.     //This is a read/write attribute. 
  32.     public virtual bool Reviewed
  33.     {
  34.         get {return reviewed;}
  35.     set {reviewed = value;}
  36.     }
  37. }

四、检索存储在属性中的信息

    1、检索自定义属性的过程很简单。
                  首先,声明要检索的属性实例。
                   然后,使用 Attribute.GetCustomAttribute 方法将新属性初始化为要检索的属性值。
                  初始化新属性后,只需使用其属性获取值即可。

    2、检索属性的一个实例 

  1.  using System;
  2.   [Developer("Joan Smith""42", Reviewed = true)]
  3.   class MainApp
  4.   {
  5.       public static void Main() 
  6.       {
  7.    //Call function to get and display the attribute.
  8.    GetAttribute(typeof(MainApp));
  9.       }
  10.       
  11.       public static void GetAttribute(Type t) 
  12.       {
  13.    
  14.    
  15.    //Get instance of the attribute.    
  16.        DeveloperAttribute MyAttribute = (DeveloperAttribute) Attribute.GetCustomAttribute(t, typeof (DeveloperAttribute));
  17.        
  18.        if(null == MyAttribute)
  19.        {
  20.     Console.WriteLine("The attribute was not found.");
  21.        }
  22.        else
  23.        {
  24.     //Get the Name value.    
  25.     Console.WriteLine("The Name Attribute is: {0}." , MyAttribute.Name);
  26.     //Get the Level value.    
  27.     Console.WriteLine("The Level Attribute is: {0}." , MyAttribute.Level);
  28.     //Get the Reviewed value.
  29.     Console.WriteLine("The Reviewed Attribute is: {0}." , MyAttribute.Reviewed);
  30.        }
  31.       }
  32.   }

    3、 检索应用到同一范围的属性的多个实例

  1.  public static void GetAttribute(Type t)
  2.    {
  3.        DeveloperAttribute[] MyAttribute =
  4.        (DeveloperAttribute[]) Attribute.GetCustomAttributes(t, typeof (DeveloperAttribute));
  5.        
  6.        if(null == MyAttribute)
  7.        {
  8.     Console.WriteLine("The attribute was not found.");
  9.        }
  10.        else
  11.        {
  12.     for(int i = 0 ; i < MyAttribute.Length ; i++)
  13.     {
  14.         //Get the Name value.    
  15.         Console.WriteLine("The Name Attribute is: {0}." , MyAttribute[i].Name);
  16.         //Get the Level value.  
  17.         Console.WriteLine("The Level Attribute is: {0}." , MyAttribute[i].Level);
  18.         //Get the Reviewed value.
  19.         Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute[i].Reviewed);
  20.     }
  21.        }
  22.    }

  

    4、检索应用到不同范围的属性的多个实例

  1.  public static void GetAttribute(Type t) 
  2.   {
  3.        
  4.       DeveloperAttribute att;
  5.       //Get the class-level attributes.
  6.       
  7.       //Put the instance of the attribute on the class level in the att object.
  8.       att = (DeveloperAttribute) Attribute.GetCustomAttribute (t, typeof (DeveloperAttribute));
  9.    
  10.       if(null == att)
  11.       {
  12.    Console.WriteLine("No attribute in class {0}./n", t.ToString());
  13.       }
  14.       else
  15.       {
  16.    Console.WriteLine("The Name Attribute on the class level is: {0}.", att.Name);
  17.          Console.WriteLine("The Level Attribute on the class level is: {0}.", att.Level);
  18.          Console.WriteLine("The Reviewed Attribute on the class level is: {0}./n", att.Reviewed);
  19.       }   
  20.       //Get the method-level attributes.
  21.       //Get all methods in this class, and put them
  22.       //in an array of System.Reflection.MemberInfo objects.
  23.       MemberInfo[] MyMemberInfo = t.GetMethods();
  24.       //Loop through all methods in this class that are in the 
  25.       //MyMemberInfo array.
  26.       for(int i = 0; i < MyMemberInfo.Length; i++)
  27.       {        
  28.    att = (DeveloperAttribute) Attribute.GetCustomAttribute(MyMemberInfo[i], typeof (DeveloperAttribute));
  29.    if(null == att)
  30.    {
  31.        Console.WriteLine("No attribute in member function {0}./n" , MyMemberInfo[i].ToString());
  32.    }
  33.    else
  34.    {
  35.        Console.WriteLine("The Name Attribute for the {0} member is: {1}.", MyMemberInfo[i].ToString(), att.Name);
  36.        Console.WriteLine("The Level Attribute for the {0} member is: {1}.", MyMemberInfo[i].ToString(), att.Level);
  37.        Console.WriteLine("The Reviewed Attribute for the {0} member is: {1}./n", MyMemberInfo[i].ToString(), att.Reviewed);
  38.    }        
  39.       }
  40.   }

五、Attribute 成员

    参考 http://msdn.microsoft.com/zh-cn/library/system.attribute_members.aspx

六C#中的通用属性

    Conditional
        根据预处理标识符执行方法。Conditional 属性是 ConditionalAttribute 的别名,可应用于方法或属性类。
    Obsolete
        Obsolete 属性将某个程序实体标记为一个建议不再使用的实体。每次使用被标记为已过时的实体时,随后将生成警告或错误,这取决于属性是如何配置的。
    全局属性
        大多数属性适用于特定的语言元素,如类或方法;但是有些属性是全局的,它们适用于整个程序集或模块。例如,AssemblyVersionAttribute 属性可用于向程序集中嵌入版本信息,如下例所示:
                      [assembly: AssemblyVersion("1.0.0.0")]
        以下是一些常用的 .NET Framework 程序集级的属性:

                      AssemblyCompanyAttribute

                       AssemblyConfigurationAttribute

                       AssemblyCopyrightAttribute

                       AssemblyCultureAttribute

                       AssemblyDescriptionAttribute

                       AssemblyProductAttribute

                       AssemblyTitleAttribute

                       AssemblyTrademarkAttribute

        程序集签名属性 
        在 Visual Studio 的早期版本中,使用这些程序集级属性执行具有强名称的签名程序集

                         AssemblyKeyFileAttribute

                         AssemblyKeyNameAttribute

                         AssemblyDelaySignAttribute 
    AttributeUsage
             确定可以如何使用自定义属性类。AttributeUsage 是一个可应用于自定义属性定义的属性,自定义属性定义来控制如何应用新属性。

七、参考

    http://msdn.microsoft.com/zh-cn/library/5x6cd29c.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值