C#怎么自定义特性Attribute C# Attribute编程方法

自定义特性需继承Attribute类并用[AttributeUsage]指定作用目标、是否允许多次使用及是否可被继承;应用时用[]标记,运行时通过反射如GetCustomAttribute()读取。

在 C# 中自定义特性(Attribute)很简单,核心是继承 System.Attribute 类,并用 [AttributeUsage] 控制其使用位置和行为。

定义自定义特性类

自定义特性本质是一个类,必须继承 Attribute,推荐加上 [AttributeUsage] 来明确它能用在哪些程序元素上(比如类、方法、属性等),并决定是否允许多次使用、是否可被子类继承。

  • AttributeTargets 枚举指定作用目标,如 ClassMethodPropertyAll
  • AllowMultiple = true 表示同一位置可以标记多个该特性
  • Inherited = false 表示子类不会自动继承父类上的该特性

例如,定义一个用于标记接口实现类的特性:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ImplementsInterfaceAttribute : Attribute
{
    public Type InterfaceType { get; }
    public string Version { get; set; } = "1.0";
public ImplementsInterfaceAttribute(Type interfaceType)
{
    InterfaceType = interfaceType;
}

}

在代码中应用自定义特性

直接用方括号 [] 标记在目标元素前即可。构造函数参数写在括号里,命名参数(如 Version = "2.0")放在后面。

例如:

[ImplementsInterface(typeof(IRepository), Version = "2.0")]
public class UserRepository : IRepository
{
    // ...
}

运行时读取特性信息

用反射获取特性,常用方法有:

  • Attribute.GetCustomAttribute():获取单个特性(或 null)
  • Attribute.GetCustomAttributes():获取所有匹配特性的数组
  • 泛型版本如 GetCustomAttribute() 更安全简洁

例如检查某个类是否应用了该特性:

var type = typeof(UserRepository);
var attr = type.GetCustomAttribute();
if (attr != null)
{
    Console.WriteLine($"实现了接口:{attr.InterfaceType.Name},版本:{attr.Version}");
}

进阶技巧:带验证或逻辑的特性

特性本身不能直接执行逻辑,但可以配合其他机制实现效果。常见做法:

  • 在框架启动/注册阶段扫描类型,根据特性自动注册服务(如 ASP.NET Core 的 DI 或 MediatR)
  • 结合 Source Generator 在编译期生成代码(C# 9+)
  • 配合 AOP 框架(如 AspectCore、Fody)在方法调用前后注入行为

注意:不要在特性类中放复杂逻辑或副作用代码——它只是**元数据容器**,运行时才由你主动读取并响应。

基本上就这些。自定义特性不复杂,但容易忽略 AttributeUsage 的设置和反射读取时机,用对了能极大提升代码表达力和框架扩展性。