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

如何在表达式树中获取匿名对象的属性值?已掌握属性键获取方法

解决表达式树中匿名对象的键值对解析问题

我之前也碰到过类似的困扰,你现在已经能拿到匿名对象的属性键,但其实要获取对应的关联值(或者关联的原属性名/表达式),核心是要解析匿名对象初始化对应的MemberInitExpression,而不是只从匿名对象的类型里拿属性。因为匿名对象的属性只是个容器,真正的绑定关系藏在表达式树的Bindings集合里。

核心思路拆解

当你传入dc => new { DCCODE = dc.CompanyCode }这样的表达式时,expr.Body的实际类型是MemberInitExpression——它包含了匿名对象的所有属性绑定规则,每个绑定对应一个MemberAssignment:

  • binding.Member就是匿名对象的属性(比如DCCODE)
  • binding.Expression就是绑定的源表达式(比如dc.CompanyCode)

完整实现代码

下面是改进后的ExpressionBuilder方法,既能拿到键,也能解析对应的源属性名,甚至支持运行时求值:

public static string ExpressionBuilder<T>(Expression<Func<T, object>> expr)
{
    // 先验证表达式是否是匿名对象初始化类型
    if (expr.Body is not MemberInitExpression memberInitExpr)
    {
        throw new ArgumentException("请传入匿名对象初始化表达式", nameof(expr));
    }

    var keyValueStrings = new List<string>();

    foreach (var binding in memberInitExpr.Bindings.OfType<MemberAssignment>())
    {
        // 获取匿名对象的属性键(比如DCCODE)
        var propertyKey = binding.Member.Name;

        // 获取绑定的源表达式(比如dc.CompanyCode)
        var sourceExpr = binding.Expression;

        // 处理可能的装箱转换(因为Func<T, object>返回值会对值类型装箱)
        if (sourceExpr is UnaryExpression unaryExpr && unaryExpr.NodeType == ExpressionType.Convert)
        {
            sourceExpr = unaryExpr.Operand;
        }

        // 场景1:获取原实体的属性名(比如CompanyCode)
        if (sourceExpr is MemberExpression memberExpr)
        {
            var propertyValueName = memberExpr.Member.Name;
            keyValueStrings.Add($"{propertyKey} = {propertyValueName}");
        }
        // 场景2:如果是复杂表达式(比如dc.CompanyCode + "-" + dc.CompanyName),可以编译求值
        else
        {
            // 编译表达式,传入T实例即可拿到运行时值
            var valueFunc = Expression.Lambda<Func<T, object>>(sourceExpr, expr.Parameters).Compile();
            // 这里需要传入具体的T实例,比如var companyInstance = new Company();
            // var actualValue = valueFunc(companyInstance);
            // keyValueStrings.Add($"{propertyKey} = {actualValue}");
            keyValueStrings.Add($"{propertyKey} = [复杂表达式]");
        }
    }

    return string.Join(", ", keyValueStrings);
}

测试用法

调用示例:

// 假设Company类有CompanyCode、CompanyName属性
var result = ExpressionBuilder<Company>(dc => new { 
    DCCODE = dc.CompanyCode, 
    COMPANY_NAME = dc.CompanyName 
});
// 输出结果:"DCCODE = CompanyCode, COMPANY_NAME = CompanyName"

额外说明

  • 如果你的场景需要运行时获取具体属性值,只需要注释掉场景1的代码,启用场景2的编译逻辑,传入T类型的实例即可拿到真实值。
  • 如果源表达式是更复杂的运算(比如拼接、计算),可以用表达式访问者(ExpressionVisitor)来解析成对应的字符串,或者直接编译求值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:04:44