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

在 C# 中自定义特性(Attribute)很简单,核心是继承 System.Attribute 类,并用 [AttributeUsage] 控制其使用位置和行为。
定义自定义特性类
自定义特性本质是一个类,必须继承 Attribute,推荐加上 [AttributeUsage] 来明确它能用在哪些程序元素上(比如类、方法、属性等),并决定是否允许多次使用、是否可被子类继承。
-
AttributeTargets枚举指定作用目标,如Class、Method、Property、All等 -
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 的设置和反射读取时机,用对了能极大提升代码表达力和框架扩展性。







