C# 程序中的类型、成员和其他实体支持修饰符,这些修饰符控制它们的行为的某些方面。例如,方法的可访问性使用 public、protected、internal 和 private 修饰符控制。C# 使此功能一般化,以便能够将用户定义类型的声明信息附加到程序实体,并在运行时检索。这种附加的声明信息是程序通过定义和使用属性 (attribute) 来指定的。
下面的示例声明一个 HelpAttribute 属性,该属性可放置在程序实体上,以便提供指向其关联文档的链接。
using System; public class HelpAttribute: Attribute { string url; string topic; public HelpAttribute(string url) { this.url = url; }
public string Url { get { return url; } } public string Topic { get { return topic; } set { topic = value; } } }
所有属性类都从 .NET Framework 提供的 System.Attribute 基类派生而来。如果属性的名称以 Attribute 结尾,在引用该属性时可以省略此名称后缀。例如,HelpAttribute 属性可以按如下方式使用。
[Help("http://msdn.microsoft.com/.../MyClass.htm")] public class Widget { [Help("http://msdn.microsoft.com/.../MyClass.htm", Topic = "Display")] public void Display(string text) {} }
此示例将一个 HelpAttribute 附加到 Widget 类,并且将另一个 HelpAttribute 附加到该类中的 Display 方法。属性类的公共构造函数控制在将属性附加到程序实体时所必须提供的信息。可以通过引用属性 (attribute) 类的公共读写属性 (property) 提供附加信息(例如前面对 Topic 属性的引用)。
下面的示例演示如何使用反射在运行时检索给定程序实体的属性信息。
using System; using System.Reflection; class Test { static void ShowHelp(MemberInfo member) { HelpAttribute a = Attribute.GetCustomAttribute(member, typeof(HelpAttribute)) as HelpAttribute; if (a == null) { Console.WriteLine("No help for {0}", member); } else { Console.WriteLine("Help for {0}:", member); Console.WriteLine(" Url={0}, Topic={1}", a.Url, a.Topic); } }
static void Main() { ShowHelp(typeof(Widget)); ShowHelp(typeof(Widget).GetMethod("Display")); } }
当通过反射请求特定属性时,将使用程序源中提供的信息调用属性类的构造函数,并返回生成的属性实例。如果通过属性 (property) 提供了附加信息,那些属性(property) 将在返回属性(attribute) 实例之前被设置。
声明属性的语法糖
public string MyName { get; set; }
设定访问限制
public string MyName { get; protected internal set; }