超级爆改
This commit is contained in:
@@ -8,130 +8,32 @@ public static class ReflectionHelper
|
||||
{
|
||||
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
|
||||
// --- 设置值 (支持 object, 支持 List/Array 下标) ---
|
||||
// --- 寻址缓存核心区 ---
|
||||
private static readonly Dictionary<string, DeepAccessor> _accessors = new Dictionary<string, DeepAccessor>();
|
||||
|
||||
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;
|
||||
string[] parts = path.Split('.');
|
||||
SetDeepValueRecursiveWithList(target, parts, 0, newValue);
|
||||
GetAccessor(target.GetType(), path).SetValue(target, newValue);
|
||||
}
|
||||
|
||||
private static void SetDeepValueRecursiveWithList(object currentObj, string[] pathParts, int index, object newValue)
|
||||
{
|
||||
string memberName = pathParts[index];
|
||||
Type type = currentObj.GetType();
|
||||
int idx;
|
||||
bool isIndex = int.TryParse(memberName, out idx);
|
||||
bool isLast = index == pathParts.Length - 1;
|
||||
|
||||
if (isIndex)
|
||||
{
|
||||
// List/Array 下标
|
||||
if (currentObj is System.Collections.IList list && idx >= 0 && idx < list.Count)
|
||||
{
|
||||
if (isLast)
|
||||
{
|
||||
list[idx] = newValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
object nextObj = list[idx];
|
||||
SetDeepValueRecursiveWithList(nextObj, pathParts, index + 1, newValue);
|
||||
// Struct 回写
|
||||
if (nextObj != null && nextObj.GetType().IsValueType)
|
||||
list[idx] = nextObj;
|
||||
}
|
||||
}
|
||||
else if (type.IsArray && idx >= 0 && idx < ((Array)currentObj).Length)
|
||||
{
|
||||
Array arr = (Array)currentObj;
|
||||
if (isLast)
|
||||
{
|
||||
arr.SetValue(newValue, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
object nextObj = arr.GetValue(idx);
|
||||
SetDeepValueRecursiveWithList(nextObj, pathParts, index + 1, newValue);
|
||||
if (nextObj != null && nextObj.GetType().IsValueType)
|
||||
arr.SetValue(nextObj, idx);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
FieldInfo field = type.GetField(memberName, Flags);
|
||||
PropertyInfo prop = type.GetProperty(memberName, Flags);
|
||||
if (field == null && prop == null) return;
|
||||
|
||||
if (isLast)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (field != null) field.SetValue(currentObj, newValue);
|
||||
else if (prop != null && prop.CanWrite) prop.SetValue(currentObj, newValue);
|
||||
}
|
||||
catch (Exception e) { Debug.LogError($"设置值失败 {memberName}: {e.Message}"); }
|
||||
}
|
||||
else
|
||||
{
|
||||
object nextObj = field != null ? field.GetValue(currentObj) : prop.GetValue(currentObj);
|
||||
if (nextObj == null) return;
|
||||
SetDeepValueRecursiveWithList(nextObj, pathParts, index + 1, newValue);
|
||||
if (nextObj.GetType().IsValueType)
|
||||
{
|
||||
if (field != null) field.SetValue(currentObj, nextObj);
|
||||
else if (prop != null && prop.CanWrite) prop.SetValue(currentObj, nextObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- 获取值 (支持 object, 支持 List/Array 下标) ---
|
||||
// --- 【无感替换口】获取深层递归值 ---
|
||||
public static object GetDeepValue(object target, string path)
|
||||
{
|
||||
object current = target;
|
||||
foreach (string part in path.Split('.'))
|
||||
{
|
||||
if (current == null) return null;
|
||||
Type type = current.GetType();
|
||||
|
||||
// 检查是否为下标访问
|
||||
int idx;
|
||||
if (int.TryParse(part, out idx))
|
||||
{
|
||||
// List/Array 下标
|
||||
if (current is System.Collections.IList list && idx >= 0 && idx < list.Count)
|
||||
{
|
||||
current = list[idx];
|
||||
continue;
|
||||
}
|
||||
else if (type.IsArray && idx >= 0 && idx < ((Array)current).Length)
|
||||
{
|
||||
current = ((Array)current).GetValue(idx);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null; // 下标无效
|
||||
}
|
||||
}
|
||||
|
||||
FieldInfo field = type.GetField(part, Flags);
|
||||
if (field != null)
|
||||
{
|
||||
current = field.GetValue(current);
|
||||
continue;
|
||||
}
|
||||
|
||||
PropertyInfo prop = type.GetProperty(part, Flags);
|
||||
if (prop != null)
|
||||
{
|
||||
current = prop.GetValue(current);
|
||||
continue;
|
||||
}
|
||||
return null; // 路径中断
|
||||
}
|
||||
return current;
|
||||
if (target == null || string.IsNullOrEmpty(path)) return null;
|
||||
return GetAccessor(target.GetType(), path).GetValue(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -252,6 +154,156 @@ public static class ReflectionHelper
|
||||
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 信息
|
||||
|
||||
Reference in New Issue
Block a user