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

LINQ反射表达式访问嵌套属性抛出异常的解决方法

解决嵌套LINQ Expression属性访问的TargetException问题

你的问题出在手动解析表达式树时只处理了单层属性访问,当遇到嵌套属性(比如m.Name.First)时,表达式树是多层嵌套的MemberExpression,直接用根对象Person去获取最内层属性的值自然会类型不匹配。

最简单的解决方案:编译表达式委托

其实你完全不用手动解析表达式树,直接把Expression<Func<Person, string>>编译成可执行的委托,它会自动处理所有嵌套的成员访问逻辑:

public static void OutputField(Person p, Expression<Func<Person, string>> outExpr)
{
    // 编译表达式为委托,自动处理嵌套属性
    var getValue = outExpr.Compile();
    string v = getValue(p);
    Console.WriteLine($"value={v}");
}

这个修改后,不管是调用OutputField(person, m => m.City)还是OutputField(person, m => m.Name.First)都能正常输出结果,而且代码简洁易维护。

手动解析嵌套表达式树的方案(如果需要自定义逻辑)

如果你确实需要手动解析表达式树而不是编译,那得逐层遍历嵌套的MemberExpression,一步步计算每个成员的值:

public static void OutputField(Person p, Expression<Func<Person, string>> outExpr)
{
    object currentValue = p;
    Expression currentExpr = outExpr.Body;

    // 遍历所有嵌套的成员访问节点
    while (currentExpr is MemberExpression memberExpr)
    {
        var property = (PropertyInfo)memberExpr.Member;
        // 用当前值作为目标,获取下一层属性的值
        currentValue = property.GetValue(currentValue, null);
        // 移动到上一层表达式节点
        currentExpr = memberExpr.Expression;
    }

    string v = currentValue.ToString();
    Console.WriteLine($"value={v}");
}

为什么原来的代码会报错?

当你传入m => m.Name.First时,表达式树的结构是:

  • 最外层是MemberExpression(对应First属性),它的Expression是另一个MemberExpression(对应Name属性)
  • 而Name属性的Expression才是参数m(Person实例)

原来的代码直接拿First属性去调用prop.GetValue(p, null),相当于试图从Person实例获取First属性,这显然类型不匹配,所以抛出了TargetException。

关于你提到的"Combine lambda expressions to retrieve nested values"

这个思路本质上就是处理嵌套表达式树的遍历逻辑,上面的手动解析方案就是这个思路的具体实现——逐层拆解表达式树,依次计算每个成员的值,最终得到嵌套属性的结果。

内容的提问来源于stack exchange,提问作者John Bruestle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:25:38