自定义特性(Attribute)
目录
在 C# 世界里,自定义特性 (Attribute) 就像在武林里为门派和武功贴上标签:
哪一门、什么境界、需要多长冷却、是否禁术…… 都能靠它来标注。
一、如何定义一个特性(AttributeUsage)
要创建一个自定义特性,只需要继承 System.Attribute。
但作为“武侠标签”,我们通常还要规定它能标注在哪里:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
public class WuxiaAttribute : Attribute
{
}AttributeTargets 可选值包括:
- Class(类)
- Method(方法)
- Property(属性)
- Field(字段)
- Parameter(参数)
- Assembly(程序集)
- Interface 等等…
关键概念:
用法说明AllowMultiple同一目标是否允许多个特性Inherited子类是否能继承这个特性
示例:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class MartialArtAttribute : Attribute
{
}二、特性如何传参数(构造函数 + 属性)
武侠标签当然不能只有名字,你可以传入:
- 门派
- 武力等级
- 冷却时间
- 是否禁术
示例:定义一个【武功秘籍特性】
public class SkillAttribute : Attribute
{
public string Sect { get; }
public int PowerLevel { get; }
public float Cooldown { get; set; }
public SkillAttribute(string sect, int powerLevel)
{
Sect = sect;
PowerLevel = powerLevel;
}
}说明:
- 必须参数 → 写到构造函数
- 可选参数 → 用属性定义(如 Cooldown)
示例用法:
[Skill("少林", 9, Cooldown = 10.5f)]
public class 龙爪手
{
}三、如何读取自定义特性(反射)
武林高手当然能看懂秘籍的隐藏属性——
这就需要 反射。
读取类上的特性:
var type = typeof(龙爪手);
var attr = (SkillAttribute)Attribute.GetCustomAttribute(type, typeof(SkillAttribute));
Console.WriteLine($"门派:{attr.Sect} 等级:{attr.PowerLevel} 冷却:{attr.Cooldown}");读取方法上的特性:
var methods = type.GetMethods();
foreach (var m in methods)
{
var a = m.GetCustomAttribute<SkillAttribute>();
if (a != null)
{
Console.WriteLine($"{m.Name} 来自 {a.Sect}, 等级 {a.PowerLevel}");
}
}读取属性上的特性:
var props = type.GetProperties();
foreach (var p in props)
{
var a = p.GetCustomAttribute<SkillAttribute>();
if (a != null)
{
Console.WriteLine($"属性 {p.Name} 标签:{a.Sect} 等级 {a.PowerLevel}");
}
}反射是武林高手的“读心术”。
四、特性怎样作用于类、属性、方法
例子最清楚,我们来构建一个武侠类,满满的标签:
自定义标签 1:门派
[AttributeUsage(AttributeTargets.Class)]
public class SectAttribute : Attribute
{
public string Name { get; }
public SectAttribute(string name) => Name = name;
}自定义标签 2:武力等级(1~10)
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class PowerLevelAttribute : Attribute
{
public int Level { get; }
public PowerLevelAttribute(int level) => Level = level;
}自定义标签 3:冷却时间(秒)
[AttributeUsage(AttributeTargets.Method)]
public class CooldownAttribute : Attribute
{
public float Time { get; }
public CooldownAttribute(float time) => Time = time;
}五、实例 —— 一门完整的武功秘籍标签系统
[Sect("华山")]
[PowerLevel(7)]
public class 独孤九剑
{
[PowerLevel(9)]
[Cooldown(3.5f)]
public void 破剑式() { }
[PowerLevel(10)]
[Cooldown(5)]
public void 破刀式() { }
[PowerLevel(10)]
[Cooldown(8)]
public void 破枪式() { }
}六、如何读取这些“武功秘籍标签”
var type = typeof(独孤九剑);
// 读取类的标签
var sect = type.GetCustomAttribute<SectAttribute>();
var level = type.GetCustomAttribute<PowerLevelAttribute>();
Console.WriteLine($"【{type.Name}】门派:{sect.Name} 基础武力:{level.Level}");
foreach (var m in type.GetMethods())
{
var p = m.GetCustomAttribute<PowerLevelAttribute>();
var cd = m.GetCustomAttribute<CooldownAttribute>();
if (p != null)
{
Console.Write($"{m.Name}:武力 {p.Level}");
if (cd != null) Console.Write($" 冷却 {cd.Time} 秒");
Console.WriteLine();
}
}输出示例:
【独孤九剑】门派:华山 基础武力:7
破剑式:武力 9 冷却 3.5 秒
破刀式:武力 10 冷却 5 秒
破枪式:武力 10 冷却 8 秒这就像读取一本武功秘籍里的所有招式!
总结
| 功能 | 比喻 |
|---|---|
| 定义特性 | 创建门派规条 |
| 特性参数 | 武功的境界,招式的难度等 |
| AttributeUsage | 限定哪些人/招式能贴标签 |
| 反射读取特性 | 研读秘籍,推演武功 |
| 特性用在类/方法/属性 | 武功,心法,招式全都能标注 |