目录

C# 特性 (Attribute) 详解

在 C# 中,特性 (Attribute) 是一种强大的机制,允许开发者向程序集、模块、类型、成员等添加声明性信息(元数据)。程序可以在运行时通过反射 (Reflection) 来读取这些信息,从而改变程序的行为。

1. 什么是特性?

特性本质上是一个类,它们继承自 system:attribute 类。它们就像是贴在代码元素(类、方法、属性等)上的“标签”或“备注”。

2. 常见的使用场景

特性在 .NET 开发中无处不在,以下是一些典型的应用场景:

3. 基本语法

特性使用方括号 `[]` 包裹,放置在目标元素(类、方法、属性等)的上方。

using System;
 
// 标记这个类是可序列化的
[Serializable]
public class User
{
    // 标记这个方法已经过时,如果使用会产生警告
    [Obsolete("请使用 NewLogin 方法代替")]
    public void OldLogin()
    {
        Console.WriteLine("Old Login");
    }
 
    public void NewLogin()
    {
        Console.WriteLine("New Login");
    }
}

4. 自定义特性

你可以通过继承 `System.Attribute` 类来创建自己的特性。

4.1 定义特性类

通常特性类名以 `Attribute` 结尾(虽然使用时可以省略)。

using System;
 
// 1. 继承 System.Attribute
// 2. (可选) 使用 AttributeUsage 限制该特性可以用在哪里
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public double Version { get; set; }
 
    // 构造函数参数 -> 位置参数 (Positional Parameters)
    public AuthorAttribute(string name)
    {
        Name = name;
        Version = 1.0; // 默认值
    }
}

4.2 使用自定义特性

// 使用时可以省略 "Attribute" 后缀
// "Alice" 是位置参数,Version = 1.1 是命名参数
[Author("Alice", Version = 1.1)]
public class PaymentService
{
    [Author("Bob")]
    public void Process() 
    { 
        // ...
    }
}

5. 通过反射读取特性

特性定义好并贴上去后,如果没有代码去读取它,它就没有任何作用。我们需要使用 反射 (Reflection) 来获取这些信息。

using System;
using System.Reflection;
 
public class Program
{
    public static void Main()
    {
        // 获取 PaymentService 的类型信息
        Type type = typeof(PaymentService);
 
        // 1. 获取类上的特性
        // GetCustomAttribute 是扩展方法,需要 using System.Reflection;
        var classAuth = type.GetCustomAttribute<AuthorAttribute>();
 
        if (classAuth != null)
        {
            Console.WriteLine($"类作者: {classAuth.Name}, 版本: {classAuth.Version}");
        }
 
        // 2. 获取方法上的特性
        MethodInfo method = type.GetMethod("Process");
        var methodAuth = method.GetCustomAttribute<AuthorAttribute>();
 
        if (methodAuth != null)
        {
            Console.WriteLine($"方法作者: {methodAuth.Name}");
        }
    }
}

6. AttributeUsage 详解

`AttributeUsage` 本身也是一个特性,用来修饰你自己定义的特性类。它主要控制三个方面:

属性 描述
ValidOn 指定该特性可以应用在哪些程序元素上(类、方法、属性、字段等)。使用 `AttributeTargets` 枚举。
AllowMultiple 是否允许在同一个元素上多次使用该特性。默认为 `false`。
Inherited 派生类是否继承基类的该特性。默认为 `true`。

示例:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ColumnAttribute : Attribute { ... }

7. 总结