C# WPF动态构造Func过滤嵌套属性时抛出LessThan运算符异常
问题根因
报错核心是三个代码逻辑问题:
- 你编写的
CreateExpression方法返回值是完整的LambdaExpression对象(实际对应Func<ICommonData, double>委托类型),不是嵌套属性的成员访问表达式。直接把这个Lambda对象传入Expression.LessThan做比较,相当于尝试让一个委托类型和double值做小于运算,自然会抛出类型不匹配的异常。 - 你在
CreateFilterExpression方法中单独创建了一个ParameterExpression参数,CreateExpression方法内部又创建了另一个独立的参数实例,两个参数实例不统一,就算解决了上述类型问题,编译表达式时也会抛出参数未绑定的错误。 - 额外注意:
IEnumerable.Where是延迟执行方法,如果不调用ToList()/ToArray()等立即执行方法,过滤逻辑不会实际运行。
修复方案
- 改造嵌套属性表达式创建逻辑:不要在方法内部独立创建Parameter、也不要直接返回Lambda,改为接收外部传入的参数表达式,返回最终的成员访问表达式即可,保证整个表达式树共用同一个参数实例。
- 修正比较逻辑的左值:传入正确的Speed属性成员访问表达式,而非外层Lambda对象。
- 过滤后调用立即执行方法拿到结果。
修复后核心代码
// 构造嵌套属性访问表达式,复用外部传入的参数实例 static Expression BuildNestedPropertyAccess(Expression sourceInstance, string propertyPath) { Expression currentAccess = sourceInstance; foreach (var propName in propertyPath.Split('.')) { currentAccess = Expression.PropertyOrField(currentAccess, propName); } return currentAccess; } public static Expression<Func<TInput, bool>> CreateFilterExpression<TInput>(string filterValue) { // 整个表达式树共用同一个参数实例 ParameterExpression sourceParam = Expression.Parameter(typeof(TInput), "item"); // 拿到item.DynamicData.Speed的成员访问表达式 Expression speedAccess = BuildNestedPropertyAccess(sourceParam, "DynamicData.Speed"); // 构造 Speed < 2 的比较逻辑 Expression compareLogic = Expression.LessThan(speedAccess, Expression.Constant(2D)); // 组装最终过滤Lambda return Expression.Lambda<Func<TInput, bool>>(compareLogic, sourceParam); } private void CreateFilter(string v) { var filterFunc = CreateFilterExpression<ICommonData>(v).Compile(); // 调用ToList触发延迟执行,拿到实际过滤结果 var filteredDatas = datas.Where(filterFunc).ToList(); }
效果验证
修复后运行点击按钮触发过滤,会正确返回集合中Speed < 2的两条数据(Speed为0、1的Data实例),不会再抛出类型不匹配异常。后续扩展多条件与/或组合、其他比较规则(等于、大于、字符串包含等),只需要基于同一个sourceParam构造对应成员表达式,再通过Expression.AndAlso/Expression.OrElse拼接逻辑即可。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

