如何完成复杂查询的动态构建?( 四 )

那既然都用了 Expression 来创建子表达式了 , 那就干脆再做一点点改进 , 把x = x 5也做成从工厂方法获取 。 [ Test] publicvoidExpression09( ) {varfilter = JoinSubFilt...


那既然都用了 Expression 来创建子表达式了 , 那就干脆再做一点点改进 , 把x => x < 5也做成从工厂方法获取 。

[ Test] publicvoidExpression09( ) {varfilter = JoinSubFilters(Expression.AndAlso, CreateValueCompareFilter(Expression.GreaterThanOrEqual, 1), CreateValueCompareFilter(Expression.LessThan, 5)); varre = Enumerable.Range( 0, 10).AsQueryable .Where(filter).ToList;varexpectation = Enumerable.Range( 1, 4); re.Should.BeEquivalentTo(expectation);Expression<Func< int, bool>> CreateValueCompareFilter(Func<Expression, Expression, Expression> comparerFunc, intrightValue) {varpExp = Expression.Parameter( typeof( int), "x"); varrightExp = Expression.Constant(rightValue); varbodyExp = comparerFunc(pExp, rightExp); varresult = Expression.Lambda<Func< int, bool>>(bodyExp, pExp); returnresult; }
Expression<Func< int, bool>> JoinSubFilters(Func<Expression, Expression, Expression> expJoiner, paramsExpression<Func< int, bool>>[] subFilters) {// xvarpExp = Expression.Parameter( typeof( int), "x"); varresult = subFilters[ 0]; foreach( varsub insubFilters[ 1..]) {varleftExp = result.Unwrap(pExp); varrightExp = sub.Unwrap(pExp); varbodyExp = expJoiner(leftExp, rightExp);
result = Expression.Lambda<Func< int, bool>>(bodyExp, pExp); }
returnresult; }}
加入一点点配置 , 就完成了
最后 , 我们在把子表达式的创建通过一点点小技巧 。 通过外部参数来决定 。 就基本完成了一个多 And 的值比较查询条件的动态构建 。
[ Test] publicvoidExpression10( ) {varconfig = newDictionary< string, int> {{ ">=", 1}, { "<", 5} };varsubFilters = config.Select(x => CreateValueCompareFilter(MapConfig(x.Key), x.Value)).ToArray; varfilter = JoinSubFilters(Expression.AndAlso, subFilters); varre = Enumerable.Range( 0, 10).AsQueryable .Where(filter).ToList;varexpectation = Enumerable.Range( 1, 4); re.Should.BeEquivalentTo(expectation);Func<Expression, Expression, Expression> MapConfig( stringop ) {returnop switch{">="=> Expression.GreaterThanOrEqual, "<"=> Expression.LessThan, _ => thrownewArgumentOutOfRangeException( nameof(op)) };}
Expression<Func< int, bool>> CreateValueCompareFilter(Func<Expression, Expression, Expression> comparerFunc, intrightValue) {varpExp = Expression.Parameter( typeof( int), "x"); varrightExp = Expression.Constant(rightValue); varbodyExp = comparerFunc(pExp, rightExp); varresult = Expression.Lambda<Func< int, bool>>(bodyExp, pExp); returnresult; }
Expression<Func< int, bool>> JoinSubFilters(Func<Expression, Expression, Expression> expJoiner, paramsExpression<Func< int, bool>>[] subFilters) {// xvarpExp = Expression.Parameter( typeof( int), "x"); varresult = subFilters[ 0]; foreach( varsub insubFilters[ 1..]) {varleftExp = result.Unwrap(pExp); varrightExp = sub.Unwrap(pExp); varbodyExp = expJoiner(leftExp, rightExp);
result = Expression.Lambda<Func< int, bool>>(bodyExp, pExp); }
returnresult; }}
总结
如果逻辑关系更复杂 , 有多层嵌套像树形一样 , 比较方法也很多花样 , 甚至包含方法 , 怎么办?

特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。