在Unity中经常会遇到SerializeField
(序列化组件),HideInInspector
(在Inspector面板隐藏),Obsolete
(元素被弃用)等特性(Attribute)。但你有真正了解过它是怎样起作用的嘛?以及如何创建自定义特性嘛?
特性的作用
可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。 将特性与程序实体相关联后,可以在运行时使用反射这项技术查询特性。(出自微软官方文档)
如何使用特性
特性的使用就是直接把特性中括号包起来放在字段、属性、方法等的上方即可,如下:
1 2 3 4
| [MethodImpl(MethodImplOptions.InternalCall)] [NativeMethod("SetBool")] private static extern void SetBool_Internal(string key, bool value);
|
创建自定义特性
- 创建一个类直接或间接派生自
System.Attribute
即可。
- 使用
System.AttributeUsage
特性。作用是指定我们创建的特性是用在什么地方的如:Assembly、class、struct、property、method等。
- 可以根据需求设计需要传递参数或者不需要传递参数
1 2 3 4 5 6 7 8 9 10 11
| [AttributeUsage(AttributeTargets.Property)] public class SettingPropertyAttribute : Attribute{}
[AttributeUsage(AttributeTargets.Method)] public class SettingMethodAttribute : Attribute{ private string title; public SettingMethodAttribute(string title){ this.title = title; } public string Title { get { return title; } } }
|
访问特性
使用了特性标记后,肯定需要有地方调用才会生效。那要怎样调用哪?那就是:使用反射了。下面写下如何反射获取上面创建的SettingMethodAttribute
特性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies) { var class_types = assembly.GetTypes(); foreach (var class_type in class_types) { MethodInfo[] methods = class_type.GetMethods(); foreach (MethodInfo method in methods) { var attr = method.GetCustomAttribute<SettingMethodAttribute>(); if (attr != null) { Console.WriteLine(attr.Title); } } } }
|
完整实例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| namespace Study { [AttributeUsage(AttributeTargets.Method)] public class SettingMethodAttribute : Attribute { private string title; public SettingMethodAttribute(string title) { this.title = title; } public string Title { get { return title; } } }
class BuildBundleSetting { [SettingMethod("导出AB包目录")] public void method1() { } } class ConvertTable { [SettingMethod("设置表格目录")] public void method1() { }
[SettingMethod("设置导出类型")] public void method2() { } }
public class Program { static void Main(string[] args) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { var class_types = assembly.GetTypes(); foreach (var class_type in class_types) { MethodInfo[] methods = class_type.GetMethods(); foreach (MethodInfo method in methods) { var attr = method.GetCustomAttribute<SettingMethodAttribute>(); if (attr != null) { Console.WriteLine(attr.Title); } } } } } } }
|
最后
单纯的了解及使用特性并没有任何意义,特性永远都是和反射绑定在一起的。有了反射,特性才会有意义。