昨天琢磨了一整天如何将表达式树转化成条件语句,终究想不通,最终使用ExpressionVisitor,结果是半途而废。
树的解析顺序很难确定,因为无法确定用户输入了什么,当用户输入
- t => t.a > 10
或者
- t => t.a > 10 && t.b < 2
那么可以转化Expression为BinaryExpression并处理Left和Right节点以及当前的节点类型,很简单的实现转化。就算处理第二种也是好处理的,因为它的表达式树是可以很容易构造出来的。
- &&
- / \
- > <
- / \ / \
- t.a 10 t.b 2
看到这颗树,再结合已知属性很容易就实现转化,这其中如果说困难,也就难在大量的ExpressionType枚举的判断上。可那也只是时间问题。重要的是如果用户输入再复杂的呢。
- // x为局部变量
- t => t.a > ints[0] && t.b < x || t.c != 2
例如上例我不知道怎么办了。最终放弃这个想法,因为微软已经实现了将Lambda转化为SQL了。但还是不太想放弃,睡觉时无意想到,如果这样做
- Expression<Func<T, bool>> lambda = (t) => t.A > 10 && t.B < 2;
- Console.WriteLine(lambda.ToString());
- // 控制台显示 t => ((t.A > 10) AndAlso (t.B < 2))
由此可见在表达式已经自己变成字符串了,之后去查找替换特定的字符串不就可以了。
真是“踏破铁鞋无觅处,得来全不费工夫”。那么剩下的问题就剩下更复杂的解析了,如上一个示例,对变量、数组、集合的访问在树中会被解析为特定的节点,初步想法仍然是在访问器中获取并后期替换,不知道还有么有更好的想法。