# 表达式目录树

## 表達式目錄樹

### 2.表達式目錄樹如何聲明

Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树

2. 自己拼裝

ConstantExpression：常量值表達式
BinaryExpression：二元運算符表達式
ParameterExpression：參數表達式
ConstantExpression conLeft = Expression.Constant(345);
ConstantExpression conRight = Expression.Constant(456);
Expression<Action> actExpression = Expression.Lambda<Action>(binary, null);//()=>345+456
//只能执行表示Lambda表达式的表达式目录树，即LambdaExpression或者Expression<TDelegate>类型。如果表达式目录树不是表示Lambda表达式，需要调用Lambda方法创建一个新的表达式
actExpression.Compile()();//()=>345+456


### 3.如何修改表達式目錄樹

1) 自己寫的一個隊操作符操作的Visitor，首先必須的繼承自ExpressionVisitor抽象父類,來自 System.Linq.Expressions命名空間

public class OperationsVisitor:ExpressionVisitor
{
public Expression Modify(Expression node)
{
return base.Visit(node);
}

protected override Expression VisitBinary(BinaryExpression node)
{
{
Expression left = Modify(node.Left);
Expression right= Modify(node.Right);
return Expression.Subtract(left,right);
}
return base.VisitBinary(node);
}

protected override Expression VisitParameter(ParameterExpression node)
{
return base.VisitParameter(node);
}

protected override Expression VisitConstant(ConstantExpression node)
{
return base.VisitConstant(node);
}
}


Expression<Func<int,int,int>> expression = (x,y) => x * y + 3 + 2;
OperationsVisitor visitor = new OperationsVisitor();
Expression expNew = visitor.Modify(expression);


2) Sql中條件拼裝訪問器

 public class ConditionBuilderVisitor:ExpressionVisitor
{
/// <summary>
/// 棧：先進後出
/// </summary>
private Stack<string> _stringStack = new Stack<string>();

/// <summary>
/// 返回拼裝字符串
/// </summary>
/// <returns></returns>
public string Condition()
{

string condition = string.Concat(this._stringStack.ToArray());
this._stringStack.Clear();
return condition;
}

/// <summary>
/// 二元表達式
/// </summary>
/// <param name="binaryExpression"></param>
/// <returns></returns>
protected override Expression VisitBinary(BinaryExpression binaryExpression)
{
if (binaryExpression==null)
{
throw new ArgumentException("BinaryExpression");

}

this._stringStack.Push(")");
base.Visit(binaryExpression.Right);//解析右邊
this._stringStack.Push(" " + binaryExpression.NodeType.ToSqlOperator() + " ");
base.Visit(binaryExpression.Left);//解析左邊
this._stringStack.Push("(");
return binaryExpression;
}

/// <summary>
/// 成員表達式
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
protected override Expression VisitMember(MemberExpression node)
{
if (node==null)
{
throw new ArgumentException("MemberExpression");
}
this._stringStack.Push(" [" + node.Member.Name + "] ");
return node;
}

/// <summary>
/// 常量
/// </summary>
/// <param name="constantExpression"></param>
/// <returns></returns>
protected override Expression VisitConstant(ConstantExpression constantExpression)
{
if (constantExpression==null)

{
throw new ArgumentException("ConstantExpression");
}

this._stringStack.Push("'"+ constantExpression.Value+"'");
return constantExpression;
}

protected override Expression VisitMethodCall(MethodCallExpression methodCall)
{
if (methodCall==null)
{
throw new ArgumentException("MethodCallExpression");
}

string format;
switch(methodCall.Method.Name)
{
case "StartsWith":
format = "({0} LIKE {1}+'%')";
break;

case "Contains":
format = "({0} LIKE '%'+{1}+'%')";
break;

case "EndsWith":
format = "({0} LIKE '%'+{1})";
break;

default:
throw new NotSupportedException(methodCall.NodeType + " is not supported!");
}
this.Visit(methodCall.Object);
this.Visit(methodCall.Arguments[0]);
string right = this._stringStack.Pop();
string left = this._stringStack.Pop();
this._stringStack.Push(String.Format(format, left, right));

return methodCall;
}

}


internal static  class SqlOperator
{

internal static string ToSqlOperator(this ExpressionType type)
{
switch(type)
{
case (ExpressionType.AndAlso):
case (ExpressionType.And):
return "AND";
case (ExpressionType.OrElse):
case (ExpressionType.Or):
return "OR";
case (ExpressionType.Not):
return "NOT";
case (ExpressionType.NotEqual):
return "<>";
case ExpressionType.GreaterThan:
return ">";
case ExpressionType.GreaterThanOrEqual:
return ">=";
case ExpressionType.LessThan:
return "<";
case ExpressionType.LessThanOrEqual:
return "<=";
case (ExpressionType.Equal):
return "=";
default:
throw new Exception("不支持该方法");
}
}
}


 Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Id > 5
&& x.Name.StartsWith("1")
&& x.Name.EndsWith("1")
&& x.Name.Contains("1");

//string sql = string.Format("Delete From [{0}] WHERE {1}"
//    , typeof(People).Name
//    , " [Age]>5 AND [ID] >5"
//    );
ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
vistor.Visit(lambda);
Console.WriteLine(vistor.Condition());