C#如何从Lambda表达式中提取包含数组索引的完整属性路径
基于Lambda表达式获取带数组索引的完整属性路径
你现有的实现无法提取索引值,是因为仅处理了MemberExpression类型的表达式节点,而数组/列表的[]访问属于IndexExpression类型,需要单独追加该类型的解析逻辑。
完整工具类实现
using System.Linq.Expressions; using System.Reflection; public static class ExpressionUtils { public static string PathString<T>(Expression<Func<T>> expression) { var pathParts = new Stack<string>(); var currentNode = expression.Body; while (currentNode != null) { switch (currentNode.NodeType) { // 处理属性/字段访问节点 case ExpressionType.MemberAccess: var memberExpr = (MemberExpression)currentNode; pathParts.Push(memberExpr.Member.Name); currentNode = memberExpr.Expression; break; // 处理索引访问节点([]) case ExpressionType.Index: var indexExpr = (IndexExpression)currentNode; // 此处默认处理常量索引场景,变量索引可扩展下面的取值逻辑 if (indexExpr.Arguments.FirstOrDefault() is ConstantExpression constIndex) { var memberName = ((MemberExpression)indexExpr.Object).Member.Name; pathParts.Push($"{memberName}[{constIndex.Value}]"); currentNode = ((MemberExpression)indexExpr.Object).Expression; } else { goto default; } break; // 跳过Lambda的根参数节点 case ExpressionType.Parameter: currentNode = null; break; default: throw new NotSupportedException($"不支持的表达式节点类型:{currentNode.NodeType}"); } } return string.Join(".", pathParts); } }
调用测试
// 测试模型和你提供的一致 public class Customer { public int Id { get; set; } public Adress Adress { get; set; } public IList<Adress> Adresses { get; set; } } public class Adress { public int Id { get; set; } public int Number { get; set; } } // 执行调用 Customer customer = null; string expressionAdresses2Number = ExpressionUtils.PathString(() => customer.Adresses[2].Number); // 输出结果为 Adresses[2].Number,完全符合预期
扩展说明
- 如果需要支持变量索引(比如
() => customer.Adresses[i].Number),可以扩展IndexExpression.Arguments的取值逻辑,增加对成员访问、方法调用等节点的运行时求值处理即可。 - 也可以根据业务需求扩展支持多维数组、字典索引等其他索引场景。
内容的提问来源于stack exchange,提问作者Fernando Leal
相关产品推荐
相关产品推荐

