如何在表达式树中获取匿名对象的属性值?已掌握属性键获取方法
解决表达式树中匿名对象的键值对解析问题
我之前也碰到过类似的困扰,你现在已经能拿到匿名对象的属性键,但其实要获取对应的关联值(或者关联的原属性名/表达式),核心是要解析匿名对象初始化对应的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
相关产品推荐
相关产品推荐

