You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:09:01