Files
ichni_Creator_Studio/Assets/Scripts/Extensions/ReflectionHelper.cs

435 lines
15 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
public static class ReflectionHelper
{
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
2026-03-22 12:05:32 -04:00
// --- 寻址缓存核心区 ---
private static readonly Dictionary<string, DeepAccessor> _accessors = new Dictionary<string, DeepAccessor>();
2026-03-22 12:05:32 -04:00
public static DeepAccessor GetAccessor(Type rootType, string path)
{
2026-03-22 12:05:32 -04:00
string key = $"{rootType.FullName}:{path}";
if (!_accessors.TryGetValue(key, out var accessor))
{
2026-03-22 12:05:32 -04:00
accessor = new DeepAccessor(rootType, path);
_accessors[key] = accessor;
}
2026-03-22 12:05:32 -04:00
return accessor;
}
2026-03-22 12:05:32 -04:00
// --- 【无感替换口】设置深层递归值 ---
public static void SetDeepValue(object target, string path, object newValue)
{
if (target == null || string.IsNullOrEmpty(path)) return;
GetAccessor(target.GetType(), path).SetValue(target, newValue);
}
2026-03-22 12:05:32 -04:00
// --- 【无感替换口】获取深层递归值 ---
public static object GetDeepValue(object target, string path)
{
2026-03-22 12:05:32 -04:00
if (target == null || string.IsNullOrEmpty(path)) return null;
return GetAccessor(target.GetType(), path).GetValue(target);
}
/// <summary>
/// 遍历对象的所有字段和属性(递归地),查找值与目标值匹配的参数路径。
/// </summary>
/// <param name="target">要搜索的对象实例。</param>
/// <param name="targetValue">要匹配的目标值。</param>
/// <param name="maxDepth">递归搜索的最大深度,防止无限循环。</param>
/// <returns>返回匹配参数的完整路径列表 (例如: "position.x")。</returns>
public static List<string> FindParametersByValue(object target, object targetValue, int maxDepth = 10)
{
if (target == null || targetValue == null) return new List<string>();
// 用于存储找到的路径
var results = new List<string>();
// 用于防止循环引用(比如类 A 内部引用了类 B类 B 内部又引用了类 A
var visited = new HashSet<object>();
// 启动递归搜索
FindRecursive(target, targetValue, "", 0, results, visited, maxDepth);
return results;
}
private static void FindRecursive(
object currentObject,
object targetValue,
string currentPath,
int depth,
List<string> results,
HashSet<object> visited,
int maxDepth)
{
if (currentObject == null || depth >= maxDepth) return;
// 避免无限循环和重复搜索
// 对于值类型 (Struct) 不需要加入 visited因为它们是副本
if (!currentObject.GetType().IsValueType)
{
// 如果对象已经被搜索过,则跳过
if (visited.Contains(currentObject)) return;
visited.Add(currentObject);
}
Type currentType = currentObject.GetType();
// 1. 遍历 Field 字段
foreach (var field in currentType.GetFields(Flags))
{
// 跳过内部字段,如编译器生成的 backing fields
if (field.IsDefined(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false)) continue;
object value = field.GetValue(currentObject);
string newPath = string.IsNullOrEmpty(currentPath) ? field.Name : $"{currentPath}.{field.Name}";
CheckAndRecurse(field.FieldType, value, targetValue, newPath, depth, results, visited, maxDepth);
}
// 2. 遍历 Property 属性
foreach (var prop in currentType.GetProperties(Flags).Where(p => p.CanRead))
{
// 跳过索引器
if (prop.GetIndexParameters().Length > 0) continue;
object value = prop.GetValue(currentObject);
string newPath = string.IsNullOrEmpty(currentPath) ? prop.Name : $"{currentPath}.{prop.Name}";
CheckAndRecurse(prop.PropertyType, value, targetValue, newPath, depth, results, visited, maxDepth);
}
}
/// <summary>
/// 检查当前值是否匹配,如果不是基础类型则继续递归
/// </summary>
private static void CheckAndRecurse(
Type valueType,
object value,
object targetValue,
string newPath,
int depth,
List<string> results,
HashSet<object> visited,
int maxDepth)
{
if (value == null) return;
// 【值匹配检查】
if (value.Equals(targetValue))
{
results.Add(newPath);
return;
}
// 【递归检查】
// 只有当值是一个复杂类型Class 或 Struct时才需要递归
// 排除字符串和集合List, Array等如果你需要搜索集合内部逻辑会更复杂
if (valueType.IsClass || valueType.IsValueType && !valueType.IsPrimitive)
{
// 排除 String (虽然是 Class但我们视其为基础值)
if (valueType == typeof(string)) return;
// 排除集合(如果需要支持 List<T> 的内部搜索,你需要在这里添加处理逻辑)
if (valueType.IsArray || valueType.IsGenericType && valueType.GetInterfaces().Any(i => i == typeof(System.Collections.IEnumerable))) return;
// 递归进入下一层
FindRecursive(value, targetValue, newPath, depth + 1, results, visited, maxDepth);
}
}
/// <summary>
/// 查找对象中第一个与目标值相等的字段/属性路径(可直接用于 SetDeepValue。找不到则返回 null。
/// </summary>
public static string FindFirstParameterPathByValue(object target, object targetValue, int maxDepth = 10)
{
if (target == null || targetValue == null) return null;
var results = FindParametersByValue(target, targetValue, maxDepth);
return results.Count > 0 ? results[0] : null;
}
}
2026-03-22 12:05:32 -04:00
// --- 以下为全自动高速路由存取器 ---
public class DeepAccessor
{
private abstract class PathNode
{
public abstract object Get(object target);
public abstract void Set(object target, object value);
public abstract Type ReturnType { get; }
public abstract bool IsValueType { get; }
}
private class FieldNode : PathNode
{
private FieldInfo field;
public FieldNode(FieldInfo f) { field = f; }
public override object Get(object target) => field.GetValue(target);
public override void Set(object target, object value) => field.SetValue(target, value);
public override Type ReturnType => field.FieldType;
public override bool IsValueType => field.FieldType.IsValueType;
}
private class PropertyNode : PathNode
{
private PropertyInfo prop;
public PropertyNode(PropertyInfo p) { prop = p; }
public override object Get(object target) => prop.GetValue(target);
public override void Set(object target, object value) { if(prop.CanWrite) prop.SetValue(target, value); }
public override Type ReturnType => prop.PropertyType;
public override bool IsValueType => prop.PropertyType.IsValueType;
}
private class IndexNode : PathNode
{
private int index;
private Type returnType;
public IndexNode(int idx, Type colType)
{
index = idx;
if (colType.IsArray) returnType = colType.GetElementType();
else if (typeof(System.Collections.IList).IsAssignableFrom(colType))
{
var dictArgs = colType.GetGenericArguments();
returnType = dictArgs.Length > 0 ? dictArgs[0] : typeof(object);
}
}
public override object Get(object target)
{
if (target is System.Collections.IList list && index >= 0 && index < list.Count) return list[index];
if (target is Array arr && index >=0 && index < arr.Length) return arr.GetValue(index);
return null;
}
public override void Set(object target, object value)
{
if (target is System.Collections.IList list && index >= 0 && index < list.Count) list[index] = value;
else if (target is Array arr && index >=0 && index < arr.Length) arr.SetValue(value, index);
}
public override Type ReturnType => returnType ?? typeof(object);
public override bool IsValueType => ReturnType.IsValueType;
}
private PathNode[] nodes;
public bool IsValid { get; private set; }
public DeepAccessor(Type rootType, string path)
{
string[] parts = path.Split('.');
nodes = new PathNode[parts.Length];
Type currentType = rootType;
for (int i = 0; i < parts.Length; i++)
{
string part = parts[i];
// 数组/列表处理口
if (int.TryParse(part, out int idx))
{
nodes[i] = new IndexNode(idx, currentType);
currentType = nodes[i].ReturnType;
continue;
}
FieldInfo field = currentType.GetField(part, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
nodes[i] = new FieldNode(field);
currentType = field.FieldType;
continue;
}
PropertyInfo prop = currentType.GetProperty(part, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (prop != null)
{
nodes[i] = new PropertyNode(prop);
currentType = prop.PropertyType;
continue;
}
// 路径断裂或找不到
IsValid = false;
return;
}
IsValid = true;
}
public object GetValue(object target)
{
if (!IsValid) return null;
object current = target;
for (int i = 0; i < nodes.Length; i++)
{
if (current == null) return null;
current = nodes[i].Get(current);
}
return current;
}
public void SetValue(object target, object value)
{
if (!IsValid || target == null) return;
SetRecursive(target, 0, value);
}
// 严丝合缝拦截所有嵌套 Struct 被传值拷贝吃掉而不回写的底层 C# 坑
private void SetRecursive(object currentObj, int index, object finalValue)
{
PathNode node = nodes[index];
if (index == nodes.Length - 1)
{
node.Set(currentObj, finalValue);
return;
}
object nextObj = node.Get(currentObj);
if (nextObj == null) return;
SetRecursive(nextObj, index + 1, finalValue);
if (node.IsValueType)
{
node.Set(currentObj, nextObj);
}
}
}
public class FastReflection
{
// 定义一个节点,用来缓存每一层的 Field 或 Property 信息
private class MemberNode
{
public FieldInfo Field;
public PropertyInfo Property;
public bool IsField => Field != null;
public MemberNode(MemberInfo info)
{
if (info is FieldInfo f) Field = f;
else if (info is PropertyInfo p) Property = p;
}
// 快速获取值
public object GetValue(object target)
{
return IsField ? Field.GetValue(target) : Property.GetValue(target);
}
// 快速设置值
public void SetValue(object target, object value)
{
if (IsField) Field.SetValue(target, value);
else if (Property != null && Property.CanWrite) Property.SetValue(target, value);
}
// 判断这一层是否是 Struct (值类型),如果是,修改后需要回写
public bool IsStructType()
{
return IsField ? Field.FieldType.IsValueType : Property.PropertyType.IsValueType;
}
}
// 访问器链条
private readonly List<MemberNode> _nodes = new List<MemberNode>();
private bool _isValid = false;
/// <summary>
/// 构造函数:初始化时进行昂贵的解析操作(只做一次)
/// </summary>
public FastReflection(object rootTarget, string path)
{
if (rootTarget == null || string.IsNullOrEmpty(path)) return;
Type currentType = rootTarget.GetType();
string[] parts = path.Split('.');
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var part in parts)
{
// 查找字段或属性
FieldInfo field = currentType.GetField(part, flags);
PropertyInfo prop = currentType.GetProperty(part, flags);
if (field == null && prop == null)
{
Debug.LogError($"[FastReflection] 路径中断: 找不到成员 '{part}' 在类型 '{currentType.Name}' 中");
return;
}
// 创建节点并添加到链条
MemberNode node = new MemberNode(field ?? (MemberInfo)prop);
_nodes.Add(node);
// 更新 currentType 为下一层的类型
currentType = field != null ? field.FieldType : prop.PropertyType;
}
_isValid = true;
}
/// <summary>
/// 获取值(运行时极快)
/// </summary>
public float GetValue(object rootTarget)
{
if (!_isValid) return 0f;
object current = rootTarget;
for (int i = 0; i < _nodes.Count; i++)
{
current = _nodes[i].GetValue(current);
if (current == null) return 0f;
}
return (float)current; // 假设最后一定是 float
}
/// <summary>
/// 设置值(运行时极快,自动处理 Struct 回写)
/// </summary>
public void SetValue(object rootTarget, float newValue)
{
if (!_isValid) return;
// 开始递归处理回写
SetRecursive(rootTarget, 0, newValue);
}
// 递归函数:处理“获取-修改-回写”逻辑
private void SetRecursive(object currentObj, int index, float finalValue)
{
MemberNode node = _nodes[index];
// 1. 如果是链条的最后一个节点(即那个 float 变量)
if (index == _nodes.Count - 1)
{
node.SetValue(currentObj, finalValue);
return;
}
// 2. 如果是中间节点,先获取下一层对象
object nextObj = node.GetValue(currentObj);
if (nextObj == null) return;
// 3. 递归进入下一层
SetRecursive(nextObj, index + 1, finalValue);
// 4. 【关键】回写阶段
// 如果 nextObj 是 Struct值类型比如 Vector3
// 我们刚才在递归里修改了 nextObj 的副本,现在必须把它赋值回 currentObj
if (node.IsStructType())
{
node.SetValue(currentObj, nextObj);
}
}
}