C# 如何通过反射递归获取嵌套私有字段值(支持数组路径)
C# 递归获取嵌套私有字段(含数组支持)实现方案
核心逻辑:通过反射逐段解析路径,分别处理普通字段访问和数组下标访问,逐层取值直到拿到目标字段。
完整实现代码
using System.Reflection; using System.Text.RegularExpressions; public static class FieldAccessor { // 匹配数组索引的正则,比如 "cItems[2]" 匹配到组1:cItems,组2:2 private static readonly Regex _arrayIndexRegex = new Regex(@"^(.+)\[(\d+)\]$", RegexOptions.Compiled); public static object GetFieldValueByPath(object targetObj, string targetFieldPath) { if (targetObj == null) throw new ArgumentNullException(nameof(targetObj)); if (string.IsNullOrWhiteSpace(targetFieldPath)) throw new ArgumentNullException(nameof(targetFieldPath)); // 按点拆分路径片段 var segments = targetFieldPath.Split('.'); object currentObj = targetObj; foreach (var segment in segments) { var arrayMatch = _arrayIndexRegex.Match(segment); string fieldName; int? arrayIndex = null; if (arrayMatch.Success) { // 是数组访问,提取字段名和下标 fieldName = arrayMatch.Groups[1].Value; arrayIndex = int.Parse(arrayMatch.Groups[2].Value); } else { // 普通字段访问 fieldName = segment; } // 反射拿字段信息,支持实例的公有/私有字段 FieldInfo field = currentObj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { throw new ArgumentException($"字段 {fieldName} 不存在于类型 {currentObj.GetType().Name} 中"); } // 拿到字段的值 currentObj = field.GetValue(currentObj); // 如果是数组访问,取下标对应的元素 if (arrayIndex.HasValue) { if (currentObj is not Array array) { throw new ArgumentException($"字段 {fieldName} 不是数组类型,无法使用下标访问"); } if (arrayIndex.Value < 0 || arrayIndex.Value >= array.Length) { throw new IndexOutOfRangeException($"数组 {fieldName} 下标 {arrayIndex.Value} 越界,数组长度为 {array.Length}"); } currentObj = array.GetValue(arrayIndex.Value); } // 中间段值为空的话提前返回 if (currentObj == null) { return null; } } return currentObj; } // 泛型重载,方便直接转成目标类型 public static T GetFieldValueByPath<T>(object targetObj, string targetFieldPath) { var value = GetFieldValueByPath(targetObj, targetFieldPath); return value == null ? default : (T)value; } }
使用示例
注:原示例代码中C类构造函数
this.target = val为笔误,已调整为可运行版本:
public class A { private B b; public A(B b) { this.b = b; } } public class B { private C[] cItems; public B(C[] cItems) { this.cItems = cItems; } } public class C { private string target; public C(string target) { this.target = target; } } public void DoSomething(A a) { // 直接获取string类型的目标值 string val = FieldAccessor.GetFieldValueByPath<string>(a, "b.cItems[2].target"); Console.WriteLine(val); } // 测试调用 public static void Main() { var cList = new C[] { new C("第一个C"), new C("第二个C"), new C("目标C的值") }; var b = new B(cList); var a = new A(b); // 输出:目标C的值 DoSomething(a); }
支持特性
- 支持任意深度的嵌套字段访问,兼容公有/私有实例字段
- 原生支持一维数组下标访问,可扩展正则实现多维数组支持
- 包含基础的异常校验,方便排查路径错误、下标越界等问题
- 提供泛型重载,无需手动做类型转换
内容的提问来源于stack exchange,提问作者OfirD
相关产品推荐
相关产品推荐

