zoukankan      html  css  js  c++  java
  • Lambda表达式树解析(下)

    概述

      前面章节,总结了Lambda树的构建,那么怎么解析Lambda表达式树那?Lambda表达式是一种委托构造而成,如果能够清晰的解析Lambda表达式树,那么就能够理解Lambda表达式要传递的正式意图。解析Lambda表达式树意义很大,比如我们用的EF框架、Rafy框架,里面封装了大量的Lambda查询表达式,通过解析表达式转换成SQL语句,即可以查询数据库,将数据呈现给前台用户;

    Lambda表达式树解析

      下面代码块是标识Express各个节点的信息,ExpressionType.Call标识表达式中含有方法调用,常用到该类型的3个参数为:Method.DeclaringType和Argument和object。ExpressionType.Quote标识表达式中含有一元表达式,常用到的参数是Operand,里面放置了Lamble具体表达式。

    public string AnalysisExpression(Expression exp)
            {
                string TextSql = "";
                switch (exp.NodeType)
                {
                    case ExpressionType.Call:
                        {
                            MethodCallExpression mce = exp as MethodCallExpression;
                            Console.WriteLine("The Method Is {0}", mce.Method.Name);
                            Console.WriteLine("The Method TypeOf {0}", mce.Method.DeclaringType);
                            if (mce.Method.DeclaringType == typeof(string))
                            {
                                break;
                            }
                            if (mce.Method.DeclaringType != typeof(Queryable)){
                                break;
                            }
                            for (int i = 0; i < mce.Arguments.Count; i++)
                            {
    
                                TextSql+=AnalysisExpression(mce.Arguments[i]);
                            }
                        }
                        break;
                    case ExpressionType.Quote:
                        {
                            UnaryExpression ue = exp as UnaryExpression;
                            TextSql += AnalysisExpression(ue.Operand);
                        }
                        break;
                    case ExpressionType.Lambda:
                        {
                            LambdaExpression le = exp as LambdaExpression;
                            AnalysisExpression(le.Body);
                            TextSql+= ExpressTreeAnalysis.GetSqlByExpression(le.Body);
                        }
                        break;
                    case ExpressionType.AndAlso:
                    case ExpressionType.OrElse:
                    case ExpressionType.Equal:
                        {
                            BinaryExpression be = exp as BinaryExpression;
                            Console.WriteLine("The Method Is {0}", exp.NodeType.ToString());
                            TextSql += AnalysisExpression(be.Left);
                            TextSql += AnalysisExpression(be.Right);
                        }
                        break;
                    case ExpressionType.Constant:
                        {
                            ConstantExpression ce = exp as ConstantExpression;
                            Console.WriteLine("The Value Type Is {0}", ce.Value.ToString());
                        }
                        break;
                    case ExpressionType.Parameter:
                        {
                            ParameterExpression pe = exp as ParameterExpression;
                            Console.WriteLine("The Parameter Is {0}", pe.Name);
                        }
                        break;
                    default:
                        {
                            Console.Write("UnKnow");
                        }
                        break;
                }
                return TextSql;
            }

    由于自定义集合实现IQueryable和IQueryProvider来自定义查询项

    实现IQuable定义的类:

    public class BlogQueryable<T> : IQueryable<T>
        {
            BlogQueryProvider provider;
            Expression expression;
    
            public BlogQueryable(BlogQueryProvider provider)
            {
                if (provider == null)
                {
                    throw new ArgumentNullException("provider");
                }
                this.provider = provider;
                this.expression = Expression.Constant(this);
            }
    
            public BlogQueryable(BlogQueryProvider provider, Expression expression)
            {
                this.provider = provider;
                this.expression = expression;
            }
            public Type ElementType
            {
                get
                {
                    return typeof(T);
                }
            }
    
            public Expression Expression
            {
                get
                {
                    return expression;
                }
            }
    
            public IQueryProvider Provider
            {
                get
                {
                    return provider;
                }
            }
    
            public IEnumerator<T> GetEnumerator()
            {
                return ((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return ((IEnumerable)this.provider.Execute(this.expression)).GetEnumerator();
            }
    
    
            public void Where2(Expression<Func<T, bool>> func)
            {
                string TextSql = ExpressTreeAnalysis.GetSqlByExpression(func.Body);
            }
        }

    实现IQueryProvider接口的类,CreateQuery解析表达式树而Execute则是执行解析后的SQL语句,查询数据,填充list集合:

    public class BlogQueryProvider : IQueryProvider
    {
    public IQueryable CreateQuery(Expression expression) { Type elementType = expression.Type; try { return (IQueryable)Activator.CreateInstance(typeof(BlogQueryable<>).MakeGenericType(elementType), new object[] { this, expression }); } catch(TargetInvocationException tie) { throw tie.InnerException; } } public IQueryable<TElement> CreateQuery<TElement>(Expression expression) { //string TextSql= ExpressTreeAnalysis.GetSqlByExpression(((Expression)(expression as MethodCallExpression).Arguments[1]).bo); //Console.WriteLine(TextSql); AnalysisExpression(expression); return new BlogQueryable<TElement>(this, expression); } public object Execute(Expression expression) { return this.Execute2<object>(expression); } public TResult Execute<TResult>(Expression expression) { return (TResult)this.Execute2<TResult>(expression); } public TResult Execute2<TResult>(Expression expression) { return (TResult)Activator.CreateInstance(typeof(TResult)); } }

    具体下面即可使用查询

            public void MyTestMethod()
            {
                Catagory cag = new Catagory("四大名著点评");
    
                IList<Blog> Blogs = new List<Blog>();
                Blog bok = new Blog() { Title = "红楼梦", Conent = "红楼梦书籍不错",
             User = new Author() { UserName = "曹雪芹", BirefInfor = "中国清代著名作家" } }; bok.Catagories.Add(cag); bok.Catagories.Add(new Catagory("红楼梦专栏")); Blogs.Add(bok); Blog bok2 = new Blog() { Title = "三国演义", Conent = "三国鼎立时期的描述",
            User = new Author() { UserName = "罗贯中", BirefInfor = "中国元末明初著名作家" } }; bok2.Catagories.Add(cag); bok2.Catagories.Add(new Catagory("三国演义专栏")); Blogs.Add(bok2); Blog bok3 = new Blog() { Title = "西游记", Conent = "西游记讲述四个徒弟和一个师傅取经事情",
    User = new Author() { UserName = "吴承恩", BirefInfor = "中国明代杰出的小说家" } }; bok2.Catagories.Add(cag); bok2.Catagories.Add(new Catagory("西游记专栏")); Blogs.Add(bok3); Blog bok4 = new Blog() { Title = "水浒传", Conent = "描述梁山好汉劫富济贫的故事",
              User = new Author() { UserName = "施耐庵", BirefInfor = "中国明代杰出的小说家" } }; bok2.Catagories.Add(cag); bok2.Catagories.Add(new Catagory("水浒传专栏")); Blogs.Add(bok4); BlogQueryProvider Provider = new BlogQueryProvider(); BlogQueryable<Blog> Quble = new BlogQueryable<Blog>(Provider); var t2 = Quble.Where(p => p.Title == "123" && p.Conent.Contains("水浒")); }

    参考代码下载

    后续:针对解析Lambda表达式树成SQL,本人也是刚刚入门,至于完全要解析成SQL,还需要研究......

  • 相关阅读:
    pyhanlp 实体命名识别
    NABCD需求分析
    源代码
    遇到的问题和解决方法
    运行及总结
    测试与调试
    读《一个程序猿的生命周期》和《人,绩效和职业道德》有感
    面向对象程序设计
    设计类图
    SRS文档
  • 原文地址:https://www.cnblogs.com/xibei666/p/6858299.html
Copyright © 2011-2022 走看看