精华内容
下载资源
问答
  • { //修改表达式目录 Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;
  • 表达式解析树

    2020-03-18 03:43:29
    的特点 (1)每个节点有0个或多个子节点 (2)没有父节点的节点称为根节点 (3)每一个非根节点有且只有一个父节点 (4)除根节点外,每个子节点可以分为多个不相交的子树 二叉树 每个节点最多有两个子节点。 ...
    1. 树的特点
      (1)每个节点有0个或多个子节点
      (2)没有父节点的节点称为根节点
      (3)每一个非根节点有且只有一个父节点
      (4)除根节点外,每个子节点可以分为多个不相交的子树

    2. 二叉树
      每个节点最多有两个子节点。
      性质1: 在二叉树的第i层上至多有2(i-1)个结点(i>0)
      性质2: 深度为k的二叉树至多有2(k-1)个结点(k>0)
      性质3: 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
      性质4:具有n个结点的完全二叉树的深度必为 log2(n+1)
      性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根,除外)

    3. 二叉树添加元素代码,添加方式为层次遍历。一层填满再填下一层。

    class Node:
        def __init__(self,elem):
            self.elem = elem
            self.lchild = None   #左子树
            self.rchild = None   #右子树
    
    class Tree:
        def __init__(self):
            self.root = None
        def add(self,item):
            #广度遍历/层次遍历
            node = Node(item)
            if self.root is None:
                self.root = node
                return
            queue = [self.root]   #用队列操作
            while queue:
                cur_node = queue.pop(0)
                if cur_node.lchild is None:
                    cur_node.lchild = node
                    return
                else:
                    queue.append(cur_node.lchild)
                if cur_node.rchild is None:
                    cur_node.rchlid = node
                    return
                else:
                    queue.append(cur_node.rchlid)
    
    1. 二叉树遍历
      (1)广度遍历
    def breadth_travel(self):
        if self.root is None:
            return
        queue = [self.root]
        while queue:   #当queue为空,则停止循环
            cur_node = queue.pop(0)
            print(cur_node.elem)
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)
    

    (2)深度遍历
    深度遍历有三种方法。先序遍历(preorder),中序遍历(inorder),后序遍历(postorder)。
    在这里插入图片描述
    先序遍历 根节点 - > 左子树 - > 右子树

    def preorder(self,node):
        if node is None:
            return
        print(node.elem,end=' ')
        self.preorder(node.lchild)
        self.preorder(node.rchild)
    

    中序遍历 左子树 - > 根节点 - > 右子树

    def inorder(self,node):
        if node is None:
            return
        self.inorder(node.lchild)
        print(node.elem,end=' ')
        self.inorder(node.rchild)
    

    后序遍历 左子树 - > 右子树 - > 根节点

    def postorder(self,node):
        if node is None:
            return
        self.postorder(node.lchild)
        self.postorder(node.rchild)    
        print(node.elem,end=' ')   
    

    题目:给出先序遍历和中序遍历,写出后序遍历
    或:给出后序遍历和中序遍历,写出先序遍历
    解析:先序遍历的第一个是根节点,后序遍历的最后一个是根节点,找到根节点就可以在中序中划分出左子树和右子树

    1. 用嵌套列表实现二叉树
    def binaryTree(r):
        return [r,[],[]]
    
    def insertLeft(root,newBranch):
        t=root.pop(1)
        root.insert(1,[newBranch,t,[]])
        return root
    
    def insertRight(root,newBranch):
        t=root.pop(2)
        root.insert(2,[newBranch,[],t])
        return root
    
    def getRootVal(root):
        return root[0]
    
    def setRootVal(root,newVal):
        root[0]=newVal
        
    def getLeftChild(root):
        return root[1]
    
    def getRightChild(root):
        return root[2]
    
    r=binaryTree(3)
    insertLeft(r,4)
    insertRight(r,5)
    insertLeft(r,9)
    insertRight(r,7)
    l=getLeftChild(r)
    print(r)
    print(l)
    insertLeft(l,11)
    print(r)
    

    输出

    [3, [9, [4, [], []], []], [7, [], [5, [], []]]]
    [9, [4, [], []], []]
    [3, [9, [11, [4, [], []], []], []], [7, [], [5, [], []]]]

    1. 树的应用
      表达式解析树 全括号表达式(3 *( 5 + 6 ))

    步骤:从左到右扫描全括号表达式的每个单词,

    • 若当前单词为"(":则在当前节点添加一个新节点作为其左子节点,当前节点下降为这个新结点
    • 如果当前单词是操作数:将当前节点的值设为此数,当前节点上升到父节点
    • 如果当前单词是操作符 “+,-,*,/”:将当前节点的值设为此符号,为当前节点添加一个新节点作为其右子节点,当前节点下降为这个新节点
    • 如果当前单词是")":则当前节点上升到父节点
    import operator
    
    class binaryTree:
        def __init__(self,root):
            self.root=None
            self.leftChild=None
            self.rightChild=None
            
        def insertLeft(self,newNode):
            if self.leftChild==None:
                self.leftChild=binaryTree(newNode)
            else:
                t=binaryTree(newNode)
                t.leftChild=self.leftChild
                self.leftChild=t
                
        def insertRight(self,newNode):
            if self.rightChild==None:
                self.rightChild=binaryTree(newNode)
            else:
                t=binaryTree(newNode)
                t.rightChild=self.rightChild
                self.rightChild=t  
        
        def getRightChild(self):
            return self.rightChild
        
        def getLeftChild(self):
            return self.leftChild
        
        def setRootVal(self,item):
            self.root=item
            
        def getRootVal(self):
            return self.root
    
    def buildParseTree(fplist):
        pStack=[]
        eTree=binaryTree('')
        pStack.append(eTree)
        currentTree=eTree
        
        for i in fplist:
            if i=='(':
                currentTree.insertLeft('')
                pStack.append(currentTree)
                currentTree=currentTree.getLeftChild()
            elif i not in ['+','-','*','/',')']:
                currentTree.setRootVal(int(i))
                parent=pStack.pop()
                currentTree=parent
            elif i in ['+','-','*','/']:
                currentTree.setRootVal(i)
                currentTree.insertRight('')
                pStack.append(currentTree)
                currentTree=currentTree.getRightChild()
            elif i==')':
                pStack.pop()
            else:
                raise ValueError       
        return eTree
    
    def evaluate(parseTree):
        opers={'+':operator.add,'-':operator.sub,\
               '*':operator.mul,'/':operator.truediv}
        
        leftC=parseTree.getLeftChild()
        rightC=parseTree.getRightChild()
        
        if leftC and rightC:
            fn=opers[parseTree.getRootVal()]
            return fn(evaluate(leftC),evaluate(rightC))
        else:
            return parseTree.getRootVal()
        
    alist=['(','5','*','(','7','+','8',')',')']
    e=buildParseTree(alist)
    print(evaluate(e))   #75
    
    展开全文
  • 书接上回,一般正常的lambda表达式被接收到后,基本上都是以这种类型被做解析。 首先我们来看看LambdaExpression这个类型。 一、它是干嘛的? 它捕获一个类似于.net方法主体的代码块。 LambdaExpression类型表示...

    书接上回,一般正常的lambda表达式被接收到后,基本上都是以这种类型被做解析。

    首先我们来看看LambdaExpression这个类型。

    一、它是干嘛的?

    它捕获一个类似于.net方法主体的代码块。

    LambdaExpression 类型表示表达式树形式的 lambda 表达式。 Expression<TDelegate> 类型从 LambdaExpression 派生,并更明确地捕获 lambda 表达式的类型,也可用于表示 lambda 表达式。 在运行时,表示 lambda 表达式的表达式树节点始终为类型 Expression<TDelegate>

    LambdaExpression 的 NodeType 属性的值 Lambda

    使用 Lambda 工厂方法创建 LambdaExpression 对象。

    二、怎么使用它?

    关于这个类型中有哪些方法和属性,可以在微软文档中查找到,我就不多说了,下面说说怎么操作,并且举一个例子作为说明。

    比如我现在有一个后台管理网站,登录管理员账号,那么怎么写lambda表达式呢?

    a => a.AdminName == "admin" && a.AdminPassword == "123456"

    此处只写关键代码,当然例如“admin”这个字符串和字符串密码肯定要用变量替换,实际上这里只是一个演示,另外提前提醒大家一下,如果使用了变量,不做处理的话你会发现,我传入的变量名称叫adminName,并没有取到这个变量的值,还是以字符串的形式取到了“adminName”这个字符串,至于如何处理这个问题,后面再讲。

    怎么解析呢?

    LambdaExpression中有个属性为Body,这个属性返回的是什么呢?没错,就是后面那个方法体

    a.AdminName == "admin" && a.AdminPassword == "123456"

    而且通过断点我们会发现,在传入与解析过程中,会将一些文本标识符改变,比如“&&”会变成“AndAlso”等等,这些我们之后再讨论。

    实际上,我们取到的Body属性里面的值依然是一个Expression类型的,但通过看它(Body返回的值)的另一个属性:NodeType,会发现它的类型为XXXX,并没有用Expression结尾。

    这意味着,这个返回值的类型实际上是XXXXExpression类型,前面也有提到过一个红色字体标记的类,那个里面就包含了这些类型,不过是枚举罢了。

    一般而言,如果你看到NodeType的类型,然后在后面敲Expression会有惊喜!

    可能有人会问了,你说了半天,实际上还没有说明白怎么解析这个LambdaExpression类型的表达式啊,真是这样吗?

    看看我们拿到的body返回值,实际上是一个lambda表达式的方法体(或者叫语句),这个类型就是干这个的,实际上拿到这个返回值,就已经算解析了。

    这个是非常简单的一个Expression类型为基类下的子类,之后的其他类型解析会比这个方法要复杂一点,那么,我们下次再聊。

    展开全文
  • public class ExpressionAnalyzer { /// <summary> /// 表达式所有参数集合 /// </summary> private Dictionary<string, object> _params; /// <summary&...
    public class ExpressionAnalyzer
        {
            /// <summary>
            /// 表达式所有参数集合
            /// </summary>
            private Dictionary<string, object> _params;
            /// <summary>
            /// 命名参数别名
            /// </summary>
            private const string _argName = "TAB";
            /// <summary>
            /// 解析结果
            /// </summary>
            public AnalysisData ResultData { get; set; }
            public ExpressionAnalyzer()
            {
                ResultData = new AnalysisData()
                {
                    TableList = new Dictionary<string, AnalysisTable>(),
                    StackList = new List<string>(),
                    ParamList = new Dictionary<string, object>()
                };
                _params = new Dictionary<string, object>();
    
            }
            public ExpressionAnalyzer(LambdaExpression exp) : this()
            {
                if (exp != null)
                {
                    AppendParams(GetChildValue(exp.Body), _params);
                    foreach (var item in exp.Parameters)
                    {
                        AnalysisTables(item);
                    }
                    AnalysisExpression(exp.Body, true);
                }
            }
            /// <summary>
            /// 解析表达式
            /// </summary>
            /// <param name="exp"></param>
            /// <param name="isLeftChild"></param>
            private void AnalysisExpression(Expression exp, bool isLeftChild = true)
            {
                switch (exp.NodeType)
                {
                    case ExpressionType.AndAlso:
                        ResultData.StackList.Add("(");
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add(")");
                        ResultData.StackList.Add("AND");
                        ResultData.StackList.Add("(");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        ResultData.StackList.Add(")");
                        break;
                    case ExpressionType.OrElse:
                        ResultData.StackList.Add("(");
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add(")");
                        ResultData.StackList.Add("OR");
                        ResultData.StackList.Add("(");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        ResultData.StackList.Add(")");
                        break;
                    case ExpressionType.Equal:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add("=");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.NotEqual:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add("!=");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.GreaterThanOrEqual:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add(">=");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.GreaterThan:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add(">");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.LessThan:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add("<");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.LessThanOrEqual:
                        AnalysisExpression(GetChildExpression(exp));
                        ResultData.StackList.Add("<=");
                        AnalysisExpression(GetChildExpression(exp, false), false);
                        break;
                    case ExpressionType.Call:
                        var imExp = exp as MethodCallExpression;
                        AnalysisExpression(imExp.Object, true);
                        ResultData.StackList.Add("LIKE");
                        if (imExp.Arguments.Count > 0)
                        {
                            var arg0 = imExp.Arguments[0] as MemberExpression;
                            ResultData.StackList.Add("'%'+");
                            AnalysisExpression(imExp.Arguments[0], false);
                            ResultData.StackList.Add("+'%'");
                        }
                        break;
                    case ExpressionType.MemberAccess:
                        if (isLeftChild)
                        {
                            AnalysisTables(exp);
                            var mberExp = exp as MemberExpression;
                            var parentName = GetExpressionName(mberExp.Expression);
                            if (!string.IsNullOrEmpty(parentName))
                            {
                                ResultData.StackList.Add(string.Format("[{0}].{1}", parentName, GetExpressionName(exp)));
                                break;
                            }
                            ResultData.StackList.Add(GetExpressionName(exp));
                        }
                        else
                        {
                            var paramName = GetParamName(exp);
                            ResultData.ParamList.Add(paramName, _params[paramName]);
                            ResultData.StackList.Add(paramName);
                        }
                        break;
                    case ExpressionType.Constant:
                        var constent = exp as ConstantExpression;
                        if (constent.Value == null)
                        {
                            var op = ResultData.StackList.ElementAt(ResultData.StackList.Count - 1);
                            ResultData.StackList.RemoveAt(ResultData.StackList.Count - 1);
                            if (string.Equals(op, "="))
                            {
                                ResultData.StackList.Add("IS NULL");
                            }
                            else
                            {
                                ResultData.StackList.Add("IS NOT NULL");
                            }
                            break;
                        }
                        if (constent.Value.GetType() == typeof(String))
                        {
                            ResultData.StackList.Add(string.Format("'{0}'", constent.Value));
                            break;
                        }
                        if (constent.Value.GetType() == typeof(bool))
                        {
                            if (ResultData.StackList.Count > 0)
                            {
                                var value = Convert.ToBoolean(constent.Value);
                                ResultData.StackList.Add(string.Format("{0}", value ? "1" : "0"));
                            }
    
                            break;
                        }
                        ResultData.StackList.Add(string.Format("{0}", constent.Value));
                        break;
                    case ExpressionType.Convert:
                        var uExp = exp as UnaryExpression;
                        AnalysisExpression(uExp.Operand, isLeftChild);
                        break;
                    case ExpressionType.New:
                        var newExp = exp as NewExpression;
                        //解析查询字段
                        for (int i = 0; i < newExp.Arguments.Count; i++)
                        {
                            AnalysisExpression(newExp.Arguments[i]);
                            ResultData.StackList.Add("AS");
                            ResultData.StackList.Add(string.Format("'{0}'", newExp.Members[i].Name));
                        }
                        break;
                    case ExpressionType.Parameter:
                        //throw new BusinessException(BusinessRes.SelectObjectMastBeAnNewObject);
                        throw new Exception("ExpressionType.Parameter:");
                    //AnalysisExpression(Expression.New(exp.Type));
                    //break;
                    default:
                        break;
                }
    
            }
            /// <summary>
            /// 获取孩子节点
            /// </summary>
            /// <param name="exp"></param>
            /// <param name="getLeft"></param>
            /// <returns></returns>
            private Expression GetChildExpression(Expression exp, bool getLeft = true)
            {
                var className = exp.GetType().Name;
                switch (className)
                {
                    case "BinaryExpression":
                    case "LogicalBinaryExpression":
                        var bExp = exp as BinaryExpression;
                        return getLeft ? bExp.Left : bExp.Right;
                    case "PropertyExpression":
                    case "FieldExpression":
                        var mberExp = exp as MemberExpression;
                        return mberExp;
                    case "MethodBinaryExpression":
                        var mbExp = exp as BinaryExpression;
                        return getLeft ? mbExp.Left : mbExp.Right;
                    case "UnaryExpression":
                        var unaryExp = exp as UnaryExpression;
                        return unaryExp;
                    case "ConstantExpression":
                        var cExp = exp as ConstantExpression;
                        return cExp;
                    case "InstanceMethodCallExpressionN":
                        var imExp = exp as MethodCallExpression;
                        return imExp;
                    default:
                        return null;
                }
            }
            /// <summary>
            /// 获取变量名
            /// </summary>
            /// <param name="exp"></param>
            /// <param name="isLeftChild"></param>
            /// <returns></returns>
            private string GetExpressionName(Expression exp)
            {
                var className = exp.GetType().Name;
                switch (className)
                {
                    case "PropertyExpression":
                    case "FieldExpression":
                        var mberExp = exp as MemberExpression;
                        return string.Format("{0}", mberExp.Member.Name);
                    case "TypedParameterExpression":
                        return _argName;
                    default:
                        return string.Empty;
                }
            }
            /// <summary>
            /// 获取参数名
            /// </summary>
            /// <param name="exp"></param>
            /// <param name="isLeftChild"></param>
            /// <returns></returns>
            private string GetParamName(Expression exp)
            {
                var className = exp.GetType().Name;
                switch (className)
                {
                    case "PropertyExpression":
                    case "FieldExpression":
                        var mberExp = exp as MemberExpression;
                        return string.Format("@{0}", mberExp.Member.Name);
                    case "TypedParameterExpression":
                        var texp = exp as ParameterExpression;
                        return string.Format("@{0}", texp.Name);
                    default:
                        return string.Empty;
                }
            }
            /// <summary>
            /// 解析表信息
            /// </summary>
            /// <param name="exp"></param>
            private void AnalysisTables(Expression exp)
            {
                var className = exp.GetType().Name;
                switch (className)
                {
                    case "PropertyExpression":
                    case "FieldExpression":
                        var mberExp = exp as MemberExpression;
                        if (!IsDefaultType(mberExp.Type))
                        {
                            if (!ResultData.TableList.ContainsKey(mberExp.Member.Name))
                            {
                                ResultData.TableList.Add(mberExp.Member.Name, new AnalysisTable()
                                {
                                    Name = mberExp.Type.Name,
                                    TableType = mberExp.Type,
                                    IsMainTable = false
                                });
                            }
                        }
                        AnalysisTables(mberExp.Expression);
                        break;
                    case "TypedParameterExpression":
                        //命名参数表达式
                        var texp = exp as ParameterExpression;
                        if (!IsDefaultType(texp.Type))
                        {
                            if (!ResultData.TableList.ContainsKey(_argName))
                            {
                                ResultData.TableList.Add(_argName, new AnalysisTable()
                                {
                                    Name = texp.Type.Name,
                                    TableType = texp.Type,
                                    IsMainTable = true
                                });
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            /// <summary>
            /// 解析获取表达式的值
            /// </summary>
            /// <param name="exp"></param>
            /// <param name="leftChild"></param>
            /// <returns></returns>
            private object GetChildValue(Expression exp)
            {
                var className = exp.GetType().Name;
                switch (className)
                {
                    case "BinaryExpression":
                    case "LogicalBinaryExpression":
                        var lExp = exp as BinaryExpression;
                        var ret = GetChildValue(lExp.Left);
                        if (IsNullDefaultType(ret))
                        {
                            ret = GetChildValue(lExp.Right);
                        }
                        return ret;
                    case "MethodBinaryExpression":
                        var mbExp = exp as BinaryExpression;
                        var ret1 = GetChildValue(mbExp.Left);
                        if (IsNullDefaultType(ret1))
                        {
                            ret1 = GetChildValue(mbExp.Right);
                        }
                        return ret1;
    
                    case "PropertyExpression":
                    case "FieldExpression":
                        var mberExp = exp as MemberExpression;
                        return GetChildValue(mberExp.Expression);
                    case "ConstantExpression":
                        var cExp = exp as ConstantExpression;
                        return cExp.Value;
                    case "UnaryExpression":
                        var unaryExp = exp as UnaryExpression;
                        return GetChildValue(unaryExp.Operand);
                    case "InstanceMethodCallExpressionN":
                        var imExp = exp as MethodCallExpression;
                        if (imExp.Arguments.Count > 0)
                        {
                            return GetChildValue(imExp.Arguments[0]);
                        }
                        return null;
                    default:
                        return null;
                }
    
            }
            /// <summary>
            /// 初始化所有参数
            /// </summary>
            /// <param name="paramObj"></param>
            private void AppendParams(object paramObj, Dictionary<string, object> _params)
            {
                if (IsNullDefaultType(paramObj))
                {
                    return;
                }
                if (_params == null)
                {
                    _params = new Dictionary<string, object>();
                }
                foreach (var item in paramObj.GetType().GetProperties())
                {
                    if (IsDefaultType(item.PropertyType))
                    {
                        var value = item.GetValue(paramObj, null);
                        if (value != null)
                        {
                            _params.Add(string.Format("@{0}", item.Name), value);
                        }
                        continue;
                    }
    
                    AppendParams(item.GetValue(paramObj), _params);
                }
    
                foreach (var item in paramObj.GetType().GetFields())
                {
                    if (IsDefaultType(item.FieldType))
                    {
                        var value = item.GetValue(paramObj);
                        if (value != null)
                        {
                            _params.Add(string.Format("@{0}", item.Name), value);
                        }
                        continue;
                    }
                    AppendParams(item.GetValue(paramObj), _params);
                }
            }
            public Dictionary<string, object> GetParams(object paramObj)
            {
                Dictionary<string, object> dicParams = new Dictionary<string, object>();
                AppendParams(paramObj, dicParams);
                return dicParams;
            }
            /// <summary>
            /// 判断是否是系统默认基本类型
            /// </summary>
            /// <param name="type"></param>
            /// <returns></returns>
            private bool IsNullDefaultType(object obj)
            {
                if (obj == null)
                {
                    return true;
                }
                return IsDefaultType(obj.GetType());
            }
            private bool IsDefaultType(Type type)
            {
                string defaultType = @"String|Boolean|Double|Int32|Int64|Int16|Single|DateTime|Decimal|Char|Object|Guid";
    
                Regex e = new Regex(defaultType, RegexOptions.IgnoreCase);
                if (type.Name.ToLower().Contains("nullable"))
                {
                    if (type.GenericTypeArguments.Count() > 0)
                    {
                        return e.IsMatch(type.GenericTypeArguments[0].Name);
                    }
                }
                return e.IsMatch(type.Name);
            }
        }
        
        public class AnalysisData
        {
            public Dictionary<string, AnalysisTable> TableList { get; set; }
    
            public List<string> StackList { get; set; }
    
            public Dictionary<string, object> ParamList { get; set; }
        }
        
        public class AnalysisTable
        {
            public string Name { get; set; }
    
            public Type TableType { get; set; }
    
            public bool IsMainTable { get; set; }
        }
        
        public class TestExpressionService
        {
            public static void TestExpression()
            {
                Expression<Func<UserModel, bool>> exp = u => u.UserName.Contains("lilei") && u.Enabled == true;
                var result = new ExpressionAnalyzer(exp).ResultData;
    
                if (result.TableList.Count > 0)
                {
                    foreach (var item in result.TableList)
                    {
                        Console.WriteLine("{0} AS {1}", item.Value.Name, item.Key);
                    }
                }
                Console.WriteLine("***************************************************");
                if (result.StackList.Count > 0)
                {
                    Console.WriteLine(string.Join(" ", result.StackList));
                }
                Console.WriteLine("***************************************************");
                if (result.ParamList.Count > 0)
                {
                    foreach (var item in result.ParamList)
                    {
                        Console.WriteLine("{0}       {1}", item.Key, item.Value);
                    }
                }
            }
        }

     

    展开全文
  • 表达式树解析

    2019-04-04 13:05:00
    这个语法,where 方法里的语句很是一个lambda表达式,其实它是一个Expression,bool>>的表达式树。下面我们来看看: 例如: static void Main(string[] args) { Expression, PersonDTO>> ex = e => new ...

    相信各位在写程序时都会碰到,对象拷贝的问题。例如:

    class PersonEntity
    {
    public long Id { get; set; }
    public string Name { get; set; }
    public string XXX { get; set; }
    public int Age { get; set; }
    public DateTime CreateTime { get; set; } = DateTime.Now;
    }
    class PersonDTO
    {
    public long Id { get; set; }
    public string Name { get; set; }
    public string XXX { get; set; }
    public int Age { get; set; }
    }

      将一个PersonEntity对象的属性值,赋值给一个PersonDTO对象。一般我们的处理方式就是写一个TOXXX方法。但是如果下次换一个类,那就又得写一个TOXXX方法。而且如果类添加或者减少一个字段,那么就得修改这个方法,如果字段少,倒还好,字段一多,就凉凉。到了这里,我想大家一定会想到用反射解决这个问题,但反射有个效率问题。今天我介绍一种新的方法:那就是表达式树。说到表达式树,如果你用过EF,一定知道xxxx.Where(e=>e.Id==1)这个语法,where 方法里的语句很是一个lambda表达式,其实它是一个Expression<Func<T,bool>>的表达式树。下面我们来看看:

    例如:

            static void Main(string[] args)
            {
                Expression<Func<PersonEntity, PersonDTO>> ex = e => new PersonDTO
                {
                    Id = e.Id,
                    Name = e.Name
                };
                PersonDTO dto = ex.Compile()(new PersonEntity { Id = 1, Name = "xxx" });
    
                Console.ReadKey();
            }
    

      我们来看下编译器将它编译成什么样吧:

     1 private static void Main(string[] args)
     2         {
     3             ParameterExpression parameterExpression = Expression.Parameter(typeof(PersonEntity), "e");
     4             Expression<Func<PersonEntity, PersonDTO>> expression = Expression.Lambda<Func<PersonEntity, PersonDTO>>(Expression.MemberInit(Expression.New(typeof(PersonDTO)), new MemberBinding[]
     5             {
     6                 Expression.Bind((MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(set_Id())), Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Id())))), 
     7                 Expression.Bind((MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(set_Name())), Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle(ldtoken(get_Name()))))
     8             }), new ParameterExpression[]
     9             {
    10                 parameterExpression
    11             });
    12             PersonDTO personDTO = expression.Compile()(new PersonEntity
    13             {
    14                 Id = 1L, 
    15                 Name = "xxx"
    16             });
    17             Console.ReadKey();
    18         }

    同志们,不要慌,我们来给他梳理下,然后就变成我们看的懂的了:

     1                 Type dtoType = typeof(PersonDTO);
     2                 Type entityType = typeof(PersonEntity);
     3 
     4                 //创建一个参数表达式
     5                 ParameterExpression parameterExpression = Expression.Parameter(entityType, "e");
     6 
     7                 //创建一个访问属性表达式
     8                 MemberExpression idMemberEx = Expression.Property(parameterExpression, entityType.GetProperty("Id"));
     9                 //创建一个属性或者字段初始化表达式
    10                 MemberBinding idMemberBinding= Expression.Bind(dtoType.GetProperty("Id"),idMemberEx);
    11 
    12                 //创建一个访问属性表达式
    13                 MemberExpression nameMemberEx = Expression.Property(parameterExpression, entityType.GetProperty("Name"));
    14                 //创建一个属性或者字段初始化表达式
    15                 MemberBinding nameMemberBinding = Expression.Bind(dtoType.GetProperty("Name"), nameMemberEx);
    16 
    17                 var properMemberBindings = new MemberBinding[] {
    18                     idMemberBinding,nameMemberBinding
    19                 };
    20                 //创建一个创建对象表达式,它会自动调用该类型的无参构造函数
    21                 NewExpression dtonewex = Expression.New(dtoType);
    22                 ///创建表达式主体。用于填充 System.Linq.Expressions.MemberBinding 集合的 System.Linq.Expressions.MemberInitExpression.Bindings   对象的数组。
    23                 MemberInitExpression memberInit = Expression.MemberInit(dtonewex, properMemberBindings);
    24 
    25                 //创建一个lambda表达式,表达式主体是memberInit,参数是parameterExpression
    26                 Expression<Func<PersonEntity, PersonDTO>> expression = Expression.Lambda<Func<PersonEntity, PersonDTO>>(memberInit, new ParameterExpression[]
    27                 {
    28                     parameterExpression
    29                 });
    30                 //将表达式树生成一个委托
    31                 PersonDTO personDTO = expression.Compile()(new PersonEntity
    32                 {
    33                     Id = 1L,
    34                     Name = "xxx"
    35                 });
    36                 Console.WriteLine(personDTO.Name);

     

      运行结果为:

    我们可以将它封装下,变成我们想要的万能的TOXXX方法

        public class ValTransformationCommon<TEntity, TRes> where TEntity : class, new() where TRes : class, new()
        {
            private static IDictionary<string, Func<TEntity, TRes>> mapperDicts = new ConcurrentDictionary<string, Func<TEntity, TRes>>();
            /// <summary>
            /// 实体映射,暂且不能映射导航属性。规则是:类中的属性名字必须一样
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="obj"></param>
            /// <returns></returns>
            public static TRes Mapper(TEntity obj)
            {
                Type enType = typeof(TEntity);
                Type resType = typeof(TRes);
                string key = $"mapperKey_{enType.Name}_{resType.Name}";
                //判断缓存里是否存在该委托
                if (mapperDicts.ContainsKey(key))
                {
                    return mapperDicts[key](obj);
                }
                //创建表达式树参数
                ParameterExpression parameter = Expression.Parameter(enType, "e");
                List<MemberBinding> list = new List<MemberBinding>();
                //遍历属性
                foreach (var item in resType.GetProperties())
                {
                    var pro = enType.GetProperty(item.Name);
                    if (pro == null)
                    {
                        continue;
                    }
                    MemberExpression propertyExpression = Expression.Property(parameter, pro);
                    MemberBinding bind = Expression.Bind(item, propertyExpression);
                    list.Add(bind);
                }
                //遍历字段
                foreach (var item in resType.GetFields())
                {
                    var filed = enType.GetField(item.Name);
                    if (filed == null)
                    {
                        continue;
                    }
                    MemberExpression property = Expression.Field(parameter, filed);
                    MemberBinding bind = Expression.Bind(item, property);
                    list.Add(bind);
                }
                //将属性值和字段值复制给新的对象,
                MemberInitExpression init = Expression.MemberInit(Expression.New(resType), list);
                //获取表达式树
                Expression<Func<TEntity, TRes>> expression = Expression.Lambda<Func<TEntity, TRes>>(init, parameter);
                Func<TEntity, TRes> func = expression.Compile();
                //将委托缓存起来
                mapperDicts[key] = func;
                return func(obj);
            }     
        }

    那么它和反射相比,那个效率高呢?下面我们来对比下吧:

    反射的方法:

       static TResult TOXXX<TResult, TEntity>(TEntity entity) where TEntity : class, new() where TResult : class, new()
            {
                Type entityType = typeof(TEntity);
                Type resType = typeof(TResult);
                TResult result = (TResult)Activator.CreateInstance(resType);
                foreach (var item in entityType.GetProperties())
                {
                    var pro = resType.GetProperty(item.Name);
                    if (resType.GetProperty(item.Name) == null)
                    {
                        continue;
                    }
                    pro.SetValue(result,item.GetValue(entity));
                }
                foreach (var item in entityType.GetFields())
                {
                    var pro = resType.GetField(item.Name);
                    if (resType.GetProperty(item.Name) == null)
                    {
                        continue;
                    }
                    pro.SetValue(result, item.GetValue(entity));
                }
                return result;
            }

     

    测试的代码:

                {
                    //for (int i = 0; i < 1000; i++)
                    //{
                    //    Stopwatch stop = new Stopwatch();
                    //    stop.Start();
                    //    var en = new PersonEntity { Id = 1, Name = "1111", XXX="xxx", Age=1 };
                    //    var dto = new PersonDTO { Age = en.Age, Id = en.Id, Name = en.Name, XXX = en.XXX };
                    //    stop.Stop();
                    //    Console.WriteLine(stop.Elapsed.TotalMilliseconds);
                    //}
                }
    
                {
                    //for (int i = 0; i < 1000; i++)
                    //{
                    //    Stopwatch stop = new Stopwatch();
                    //    stop.Start();
                    //    var dto = TOXXX<PersonDTO, PersonEntity>(new PersonEntity { Id = 1, Name = "1111", XXX = "xxx", Age = 1 });
                    //    stop.Stop();
                    //    Console.WriteLine(stop.Elapsed.TotalMilliseconds);
                    //}
                }
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        Stopwatch stop = new Stopwatch();
                        stop.Start();
                        var dto = ValTransformationCommon<PersonEntity, PersonDTO>.Mapper(new PersonEntity { Id = 1, Name = "1111", XXX = "xxx", Age = 1 });
                        stop.Stop();
                        Console.WriteLine(stop.Elapsed.TotalMilliseconds);
                    }
                }

     

    我们来试下10万次的赋值看下各自的消耗时间吧

    硬编码:

    反射:

    表达式树:

     

    转载于:https://www.cnblogs.com/norain/p/10654255.html

    展开全文
  • 构建 语法解析 数学表达式

    千次阅读 2018-11-30 12:53:04
    构建 语法解析 数学表达式 本文主要讲如何把一个数学表达式转化成语法,并通过语法来解出结果。 引入 这个主要是用来学习语法的构建,数学表达式只是一个引子,本项目可以引申到 HTTP 请求报文解析,SQL...
  • 在上一阶段对字元提取的基础上,完成了表达式树的构建,通过这一表达式树的建立,可以很容易生成可顺序执行的基于堆栈的代码,这在脚本解析系统,已经编译器中是一个重要的部分。
  • 概述  前面章节,总结了Lambda的...解析Lambda表达式意义很大,比如我们用的EF框架、Rafy框架,里面封装了大量的Lambda查询表达式,通过解析表达式转换成SQL语句,即可以查询数据库,将数据呈现给前台用户; ...
  • 同时按层深度索引真值,遍历表达式的变量(按需求值),当能走到的叶子节点时说明本次表达式为true 数据结构: 1.真值:是一个二叉树,每层依次对应A,B,C...表达式成员;用真值表作为参数构造;提供...
  • 在EF中,我们查询数据时可能会用拉姆达表达式 Where(Func<T,ture> func)这个方法来筛选数据,例如,我们定义一个User实体类 public class User { public Guid Id { get; set; } public string LoginId { ...
  • //修改表达式目录 Expression<Func<int, int, int>> exp = (m, n) => m * n + 2; OperationsVisitor visitor = new OperationsVisitor(); Expression expNew = visitor.Modify(exp);
  • 解析表达式树 表达式的永久性 编译表达式 执行表达式 修改表达式 调试 简介 表达式形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。 你可以对...
  • AST语法自己写代码解析的话就比较麻烦,有现成的库可以解析PHP,就像webpack就是自己解析js的语法代码,编译成各种版本的可用代码 githubhttps://github.com/josdejong/mathjs ExtensionDescription ...
  • 线性,高效内存的解析树 运行时生成的解析器VM API用法 const char grammarSpec[] = R"( Example <- 'foo' )" ; peg::Grammar grammar; grammar.parse(grammarSpec); peg::Module module; // <- Stores code ...
  • 概述  前面章节,总结了Lambda的构建,...解析Lambda表达式意义很大,比如我们用的EF框架、Rafy框架,里面封装了大量的Lambda查询表达式,通过解析表达式转换成SQL语句,即可以查询数据库,将数据呈现给前台...
  • 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架"(3) 这3篇文章更多的是说明一种方法,一种思路,而代码比较少 在发出来之后也有些朋友互加...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 972
精华内容 388
关键字:

树解析表达式