海量编程文章、技术教程与实战案例

网站首页 > 技术文章 正文

C#语言学习笔记21 —— Attribute(属性)的使用、创建和反射读取

yimeika 2025-07-27 23:24:26 技术文章 2 ℃

C# Attributes(属性)与反射读取

Attribute 简介

Attributes(属性)提供了一种有效方式,可以把元数据(metadata)和声明性信息(declarative information)与程序代码(assemblies, types, methods, properties 等等)关联起来。

通过 attributes 把元数据和程序里的实体(entity)关联以后,在程序运行过程中,通过反射(reflection),就可以查询到关联的 attributes,然后加以利用。

.Net 本身已经定义许多有用的 attributes,我们也可以定义自己的 attributes。

.Net 定义的 Attributes

先看几个 .Net 里面的 attributes:

  • ObsoleteAttribute,标记程序实体已过时,不再使用,编译器会产生警告(或错误)。
  • ConditionalAttribute,条件属性,编译根据条件是否符合,发出方法调用代码,或不发出。
  • CLSCompliantAttribute,指示检查程序元素是否符合公共语言规范 (CLS)。如果开发的类库需要在多语言(如C#、VB.NET)环境下使用,这个检查很有帮助。
  • FlagsAttribute,指示枚举可以当作位标志来对待,如枚举的值为:1、2、4、8、16、... 等。

下面是一个使用 ObsoleteAttribute 的代码片段例子。

下面是一个使用 ConditionalAttribute 的完整代码例子, 可以有选择性地注释掉最前面定义 CONDITION1、CONDITION2 的那两行, 然后重新编译运行程序,看程序输出有什么不同。

使用 Attribute 的场景举例:

  • 在 Web 服务中,将控制器方法(controller methods)标志为 [ HttpPost ]
  • 本机代码互操作的方法指定 [ MarshalAs(...) ]
  • 使用于 Component Object Model (COM) 的类、方法、接口
  • 调用非托管代码 [ DllImport(...) ]
  • 描述程序集的标题、版本、描述、商标等信息
  • 描述类成员的持久序列化
  • 描述类成员序列化时和 xml 节点的映射关系
  • 描述方法的安全要求
  • 描述强制指定安全要求
  • 控制编译器对即时编译(just-in-time)(JIT)的代码生成
  • 获取调用者(caller)的信息

Attribute 语法

在 C#, 指定一个 attribute,把 attribute 名放在方括号 [ ] 中,放在要应用的实体前面。

依照惯例,attribute 的类名有后缀 "Attribute",但使用时则省略后缀。 例如:Serializable 的类名为 SerializableAttribute,使用名为 [Serializable]

(1)Attribute 的参数

许多 attributes 是带有参数的,可以按位置的、可以是命名的。

位置参数:

  • 不能缺省
  • 在参数列表中放在前面
  • 顺序固定

命名参数:

  • 可选的
  • 要放在位置参数后面
  • 顺序随意

Attributes 的参数类型限制为简单类型,bool、int、double、string、Type、enums等等,或者这些类型的数组。 而且要为字面量(literals)形式,不能使用表达式或变量。

(2)Attribute 的目标(target)

Attribute 的目标是 attribute 所应用于的实体。

语法:[target : attribute-list]

assembly

整个程序集(assembly)

module

当前程序集的模块(module)

field

类或结构体中的字段

event

事件(Event)

method

方法或 get 和 set 属性访问器(property accessors)

param

方法的参数或 set 属性访问器(property accessor)的参数

property

属性(Property)

return

返回来自方法、属性索引器(property indexer)或 get 属性访问器(property accessor)的值

type

结构体、类、接口、枚举或委托

创建自定义 Attributes

创建一个类,直接或间接从 System.Attribute 类派生。

使用AttributeUsageAttribute,来控制 attribute 允许目标类型(ValidOn)、是否对同一个实体应用多次(AllowMultiple)、是否允许继承(Inherited)。

下面是一个 attribute 继承(Inherited)的例子(代码片段):

下面是一个 attribute 应用多次(AllowMultiple)的例子(代码片段):

下面是一个 attribute 使用参数的例子(代码片段):

反射读取 Attributes

System.Type 类是反射的中心。

调用 Attribute 的 GetCustomAttribute 或 GetCustomAttributes 方法可获得关联的 attributes 信息。

Attribute 对象是“懒实例化”(instantiated lazily)的。 调用 GetCustomAttribute 或 GetCustomAttributes 时才实例化 Attribute 来返回, 并且每次返回的都是新实例化的,不是同一个对象。

下面是一个读取 attribute 的例子(代码片段):

总结

总而言之,Attributes 的特点可归纳如下:

  • Attributes 给代码增加更多的元数据。虽然 .NET 本身已经有一套元数据了,包括类型和类型成员的元数据。 使用 attributes,可以额外添加自定义的元数据。
  • Attributes 可以加到程序集(assemblies)、模块(modules)、类(classes )、属性(properties),等等。
  • Attributes 可以接受参数。
  • 程序可以通过反射,查询自己的 attributes,或其它程序的 attributes。

Tags:

最近发表
标签列表