表达式树解析"框架"(3)(一)

2014-11-24 03:00:21 · 作者: · 浏览: 2
这应该是年前最后一篇了,接下来的时间就要陪陪老婆孩子了
  关于表达式树解析也是最后一篇了,该说到的中心思想都已经说到了,理解接受能力比较好的童鞋应该已经可以举一反三了
  研究表达式树的过程让我感觉微软的设计真的是非常的巧妙,也为今后我的开发之路增添了新的思路
  好了 废话不多说了 这篇主要是为了解决上篇中的提问的
声明
  解决问题的办法有很多,我只是根据我的个人习惯和风格介绍我的解决方案,并不一定就是最好的,仅仅只是提供一种思路,大家可以根据自己或项目的实际情况酌情对待
  关于问题请参考干货!表达式树解析"框架"(2)结尾
问题一
db.Where(u => u.Name != null); //u.Name is not null 而非( u.Name <> null )
分析
  这个问题主要是在Sql中`二元表达式`有一个非常特别的情况,如果和null进行比较,那么应该用is或is not 而不是=或者<>(!=)
  so~我的做法是在解析二元表达式的类中处理,如第二个参数是null,且符号是Equals或NotEqual,则使用is/is not
  怎么判断第二个参数是null
  这里我打算直接判断ParserArgs.Builder中最后5个字符,如果是 " NULL" 就算是NULL了
  但是这里有个问题,就是原来的操作是先加入符号,再加入Right的,所以这里也要改,改为先放入Right再插入符号
代码如下
复制代码
class BinaryExpressionParser : ExpressionParser
{
public override void Where(BinaryExpression expr, ParserArgs args)
{
if (ExistsBracket(expr.Left))
{
args.Builder.Append(' ');
args.Builder.Append('(');
Parser.Where(expr.Left, args);
args.Builder.Append(')');
}
else
{
Parser.Where(expr.Left, args);
}
var index = args.Builder.Length;
if (ExistsBracket(expr.Right))
{
args.Builder.Append(' ');
args.Builder.Append('(');
Parser.Where(expr.Right, args);
args.Builder.Append(')');
}
else
{
Parser.Where(expr.Right, args);
}
var length = args.Builder.Length;
if (length - index == 5 &&
args.Builder[length - 5] == ' ' &&
args.Builder[length - 4] == 'N' &&
args.Builder[length - 3] == 'U' &&
args.Builder[length - 2] == 'L' &&
args.Builder[length - 1] == 'L')
{
Sign(expr.NodeType, index, args, true);
}
else
{
Sign(expr.NodeType, index, args);
}
}
/// 判断是否需要添加括号
///
private static bool ExistsBracket(Expression expr)
{
var s = expr.ToString();
return s != null && s.Length > 5 && s[0] == '(' && s[1] == '(';
}
private static void Sign(ExpressionType type, int index, ParserArgs args, bool useis = false)
{
switch (type)
{
case ExpressionType.And:
case ExpressionType.AndAlso:
args.Builder.Insert(index, " AND");
break;
case ExpressionType.Equal:
if (useis)
{
args.Builder.Insert(index, " IS");
}
else
{
args.Builder.Insert(index, " =");
}
break;
case ExpressionType.GreaterThan:
args.Builder.Insert(index, " >");
break;
case ExpressionType.GreaterThanOrEqual:
args.Builder.Insert(index, " >=");
break;
case ExpressionType.NotEqual:
if (useis)
{
args.Builder.Insert(index, " IS NOT");
}
else
{
args.Builder.Insert(index, " <>");
}
break;
cas