能否使用ExpressionVisitor遍历表达式体成员并获取其Getter的Expression?
问题前置提醒
你给出的示例代码存在递归错误:LinePrice的getter访问了自身,运行时会触发无限递归导致栈溢出,正确的计算逻辑应该是Quantity * UnitPrice。
实现方案
表达式体属性(=> 定义的getter)默认编译为普通IL方法,不会直接生成可直接读取的Expression对象,你可以通过两种方案实现需求:
方案1:可修改类定义时优先使用(最稳定高效)
直接把计算逻辑封装为公开的静态表达式字段,属性直接调用编译后的表达式委托:
class OrderLine : Table { public int Id { get; set; } public Order Order { get; set; } public decimal Quantity { get; set; } public decimal UnitPrice { get; set; } // 预定义计算逻辑的表达式树 public static readonly Expression<Func<OrderLine, decimal>> LinePriceExpression = ol => ol.Quantity * ol.UnitPrice; // 缓存编译后的委托,避免重复编译损耗 private static readonly Func<OrderLine, decimal> _linePriceGetter = LinePriceExpression.Compile(); [CalculatedField] public decimal LinePrice => _linePriceGetter(this); }
需要读取表达式时,通过反射拿到对应静态字段即可:
var calculatedProp = typeof(OrderLine).GetProperties() .First(p => p.GetCustomAttribute<CalculatedFieldAttribute>() != null); // 按约定读取对应表达式字段 var exprField = typeof(OrderLine).GetField($"{calculatedProp.Name}Expression", BindingFlags.Public | BindingFlags.Static); var linePriceExpr = (LambdaExpression)exprField.GetValue(null);
拿到的linePriceExpr可以直接传给ExpressionVisitor遍历,完全符合你构建远程请求的需求。
方案2:不可修改类定义时使用
如果不能调整现有类的代码,你需要通过IL反解析把属性getter的IL代码转换为Expression树:
- 先通过反射获取属性的get方法:
var getMethod = typeof(OrderLine).GetProperty("LinePrice").GetMethod; - 用IL解析工具读取get方法的指令流,还原为对应的表达式节点。自己完整实现IL到表达式的转换逻辑复杂度很高,你可以复用成熟的开源转换组件完成这一步。
内容的提问来源于stack exchange,提问作者eKKiM
相关产品推荐
相关产品推荐

