Skip to content

属性与反射

更新: 5/13/2026 字数: 0 字 时长: 0 分钟

自定义特性

需继承自 System.Attribute

Ex:

cs
[System.AttributeUsage(System.AttributeTargets.Class |
                       System.AttributeTargets.Struct)
]
public class AuthorAttribute : System.Attribute
{
    private string Name;
    public string Version;

    public AuthorAttribute(string name)
    {
        Name = name;
        Version = "1.0";
    }
}

像使用其他特性一样:

cs
// 为命名参数赋值时,可以用 : 替代 = 跳过有默认值的参数 
[Author("P. Ackerman", Version = "1.1")] 
class SampleClass { // P. Ackerman's code goes here... }

// 等效于
var anonymousAuthorObject = new Author("P. Ackerman") 
{ 
	Version = 1.1 
};

AttributeUsage 具有一个命名参数,可设置特性能否单次使用或多次使用。

Ex:

cs
[System.AttributeUsage(System.AttributeTargets.Class |
                       System.AttributeTargets.Struct,
                       AllowMultiple = true)  // 对此使用
]
public class AuthorAttribute : System.Attribute
{
    string Name;
    public string Version;

    public AuthorAttribute(string name)
    {
        Name = name;

        // Default value.
        Version = "1.0";
    }

    public string GetName() => Name;
}


// 使用示例:
[Author("P. Ackerman"), Author("R. Koch", Version = "2.0")]
public class ThirdClass
{
    // ...
}

使用反射访问特性

特性只是元数据,如果不用反射访问,那价值就会很小。

GetCustomAttributes() 方法返回一个对象数组。此方法有许多重载版本,参阅 Attribute

Ex:

cs
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(typeof(ThirdClass));

一个完整示例:

cs
public static class EventBinder
{
    // 游戏启动时调用!比如在 GameManager.Awake()
    public static void AutoBindAllEvents()
    {
        // 1. 找到【所有Unity脚本】(MonoBehaviour子类)
        var allMonoTypes = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(assembly => assembly.GetTypes())
            .Where(type => type.IsSubclassOf(typeof(MonoBehaviour)));

        // 2. 遍历每个脚本里的【所有方法】
        foreach (var type in allMonoTypes)
        {
            var methods = type.GetMethods();
            foreach (var method in methods)
            {
                // 3. 检查方法是否贴了 [EventBind] 特性
                var attr = method.GetCustomAttributes(typeof(EventBindAttribute), false)
                    .FirstOrDefault() as EventBindAttribute;

                if (attr == null) continue;

                // 4. 把方法自动注册到事件中心
                // bool 参数:不搜索父类继承链,仅查找当前方法自身的特性
                Action action = (Action)Delegate.CreateDelegate(typeof(Action), method);
                EventManager.Register(attr.EventId, action);

                Debug.Log($"✅ 自动绑定事件:ID={attr.EventId} → 方法={method.Name}");
            }
        }
    }
}