借助Atrribute扩展UnityEdior
借助Atrribute扩展UnityEdior
C# Attribute 简介
Attribute 是 C# 提供的一种强大的元数据机制,可以用来为代码的程序元素(如类、方法、属性等)附加额外的信息。这些附加信息可以在运行时通过反射机制读取,从而影响程序的行为。
Attribute 的特性
-
轻量级
Attribute 不会直接影响代码运行,只是附加额外信息。
-
可扩展
开发者可以创建自定义 Attribute。
-
强大
常用于代码标记、配置、工具生成、验证等场景。
Attribute 的应用范围
可以应用到以下程序元素:
- 类、结构、枚举
- 方法、构造函数
- 属性、字段
- 接口、委托
- 参数、返回值
预定义的 Attribute 示例
C# 提供了许多内置 Attribute,例如:
-
[Obsolete]
- 标记某个成员为已过时。
[Obsolete("This method is deprecated. Use NewMethod instead.")] public void OldMethod() { }
-
[Serializable]
- 标记类可以序列化。
[Serializable] public class MyClass { }
-
[DllImport]
- 用于调用非托管代码。
[DllImport("user32.dll")] public static extern int MessageBox(int hWnd, string text, string caption, uint type);
-
[Test]
- 单元测试框架中常用的 Attribute(例如 NUnit 或 MSTest)。
[Test] public void MyTestMethod() { }
自定义 Attribute
创建自定义 Attribute
- 定义一个继承自
System.Attribute
的类。 - 使用
AttributeUsage
控制 Attribute 的适用范围和行为。
[System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
public string Description { get; }
public MyCustomAttribute(string description)
{
Description = description;
}
}
使用自定义 Attribute
[MyCustomAttribute("This is a sample class.")]
public class SampleClass
{
[MyCustomAttribute("This is a sample method.")]
public void SampleMethod() { }
}
读取自定义 Attribute
通过反射读取附加的 Attribute 信息:
var type = typeof(SampleClass);
var attributes = type.GetCustomAttributes(typeof(MyCustomAttribute), false);
foreach (MyCustomAttribute attr in attributes)
{
Console.WriteLine($"Description: {attr.Description}");
}
AttributeUsage 属性
AttributeUsage
是用来定义自定义 Attribute 的使用规则的 Attribute。
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Method, // 应用范围
AllowMultiple = true, // 是否允许多次使用
Inherited = true)] // 是否能被继承
public class MyCustomAttribute : Attribute
{
// 定义逻辑
}
常见场景
- 标记元数据
- 使用 Attribute 附加描述信息,例如文档注释、开发工具的自动生成代码标记。
- 代码验证
- 结合反射读取 Attribute,用于校验输入数据。
- 控制序列化
- 通过 Attribute 标记需要序列化的字段或属性,例如 JSON 序列化。
- 单元测试
- 框架(如 NUnit、MSTest)通过 Attribute 标记测试方法。
- 绑定 UI 或框架
- 框架(如 Unity、ASP.NET)通过 Attribute 简化绑定,例如
UnityEngine.SerializeField
。
- 框架(如 Unity、ASP.NET)通过 Attribute 简化绑定,例如
优点与注意事项
优点:
- 清晰地描述额外信息。
- 可扩展性强,便于元编程。
- 通过反射可以动态控制代码行为。
注意事项:
-
性能
Attribute 的过多使用可能影响性能,尤其是需要频繁反射时。
-
复杂性
需要熟悉反射机制才能正确使用 Attribute。
-
局限性
Attribute 不支持运行时动态修改。
示例:Unity编辑器窗口获取文件路径
#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
using UnityEngine;
/// <summary>
/// Custom attribute to allow path selection in the Unity editor.
/// </summary>
public class PathSelectAttribute : PropertyAttribute
{
public string Title { get; private set; }
public string Extension { get; private set; }
public PathSelectAttribute(string title = "Select File", string extension = "*")
{
Title = title;
Extension = extension;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(PathSelectAttribute))]
public class PathSelectDrawer : PropertyDrawer
{
private string _lastSelectedPath = "";
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType != SerializedPropertyType.String)
{
EditorGUI.LabelField(position, label.text, "Use PathSelect with string.");
return;
}
PathSelectAttribute pathAttribute = (PathSelectAttribute)attribute;
EditorGUI.BeginProperty(position, label, property);
// Display the current string field
Rect textFieldPosition = new Rect(position.x, position.y, position.width - 80, position.height);
if(!string.IsNullOrEmpty(_lastSelectedPath))
property.stringValue= _lastSelectedPath;
property.stringValue = EditorGUI.TextField(textFieldPosition, label, property.stringValue);
// Create the "Browse" button
Rect buttonPosition = new Rect(position.x + position.width - 75, position.y, 75, position.height);
if (GUI.Button(buttonPosition, "Browse"))
{
// Open file panel
string path = EditorUtility.OpenFilePanel(pathAttribute.Title, "", pathAttribute.Extension);
if (!string.IsNullOrEmpty(path))
{
//使用变量保存选择的路径,避免在GUI循环中修改属性值
_lastSelectedPath = path;
}
else
{
_lastSelectedPath= String.Empty;
}
//类似打开窗口类型任务终止GUI循环时调用
GUIUtility.ExitGUI();
}
EditorGUI.EndProperty();
}
}
#endif
//------测试-------
/// <summary>
/// Example usage of PathSelectAttribute.
/// </summary>
public class PathSelectExample : MonoBehaviour
{
[PathSelect("Select a JSON file", "json")]
public string filePath;
}
总结
C# 的 Attribute 提供了一种灵活的元数据管理机制,广泛应用于框架、工具和自定义开发场景中。无论是使用预定义 Attribute,还是创建自己的 Attribute,都能极大提高代码的可读性和可扩展性。
点赞鼓励下,(づ ̄3 ̄)づ╭❤~
作者:世纪末的魔术师
出处:https://www.cnblogs.com/Firepad-magic/
Unity最受欢迎插件推荐:点击查看
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。