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; // --- 寻址缓存核心区 --- private static readonly Dictionary _accessors = new Dictionary(); public static DeepAccessor GetAccessor(Type rootType, string path) { string key = $"{rootType.FullName}:{path}"; if (!_accessors.TryGetValue(key, out var accessor)) { accessor = new DeepAccessor(rootType, path); _accessors[key] = accessor; } return accessor; } // --- 【无感替换口】设置深层递归值 --- public static void SetDeepValue(object target, string path, object newValue) { if (target == null || string.IsNullOrEmpty(path)) return; GetAccessor(target.GetType(), path).SetValue(target, newValue); } // --- 【无感替换口】获取深层递归值 --- public static object GetDeepValue(object target, string path) { if (target == null || string.IsNullOrEmpty(path)) return null; return GetAccessor(target.GetType(), path).GetValue(target); } /// /// 遍历对象的所有字段和属性(递归地),查找值与目标值匹配的参数路径。 /// /// 要搜索的对象实例。 /// 要匹配的目标值。 /// 递归搜索的最大深度,防止无限循环。 /// 返回匹配参数的完整路径列表 (例如: "position.x")。 public static List FindParametersByValue(object target, object targetValue, int maxDepth = 10) { if (target == null || targetValue == null) return new List(); // 用于存储找到的路径 var results = new List(); // 用于防止循环引用(比如类 A 内部引用了类 B,类 B 内部又引用了类 A) var visited = new HashSet(); // 启动递归搜索 FindRecursive(target, targetValue, "", 0, results, visited, maxDepth); return results; } private static void FindRecursive( object currentObject, object targetValue, string currentPath, int depth, List results, HashSet 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); } } /// /// 检查当前值是否匹配,如果不是基础类型则继续递归 /// private static void CheckAndRecurse( Type valueType, object value, object targetValue, string newPath, int depth, List results, HashSet 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 的内部搜索,你需要在这里添加处理逻辑) if (valueType.IsArray || valueType.IsGenericType && valueType.GetInterfaces().Any(i => i == typeof(System.Collections.IEnumerable))) return; // 递归进入下一层 FindRecursive(value, targetValue, newPath, depth + 1, results, visited, maxDepth); } } /// /// 查找对象中第一个与目标值相等的字段/属性路径(可直接用于 SetDeepValue)。找不到则返回 null。 /// 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; } } // --- 以下为全自动高速路由存取器 --- 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 _nodes = new List(); private bool _isValid = false; /// /// 构造函数:初始化时进行昂贵的解析操作(只做一次) /// 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; } /// /// 获取值(运行时极快) /// 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 } /// /// 设置值(运行时极快,自动处理 Struct 回写) /// 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); } } }