表达式目录树

表達式目錄樹

    • 表達式目錄樹
      • 1.什麼是表達式目錄樹
      • 2.表達式目錄樹如何聲明
      • 3.如何修改表達式目錄樹

1.什麼是表達式目錄樹

表達式目錄樹是一種語法樹,數據結構。數據都存儲在樹形結構中。

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

兩種方式,可以通過Lamada表達式聲明,也可以自己拼裝。

  1. Lamada表達式聲明:
    Expression> exp = (m, n) => m * n + 2;//lambda表达式声明表达式目录树

  2. 自己拼裝

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

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

通過ExpressionVisitor,遞歸查找所有的類型表達式,然後複寫父類的方法,對其進行相應的操作。

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)
        {
            if (node.NodeType==ExpressionType.Add)//如果二元表達式中間以加號連接
            {
                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);
        }
}

前端使用:

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

2) Sql中條件拼裝訪問器

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

        /// 
        /// 返回拼裝字符串
        /// 
        /// 
        public string Condition()
        {

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

        /// 
        /// 二元表達式
        /// 
        /// 
        /// 
        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;
        }

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

        /// 
        /// 常量
        /// 
        /// 
        /// 
        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;
        }

}

表達式類型的一個擴展方法:ToSqlOperator

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> 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());

你可能感兴趣的:(表达式目录树)