zoukankan      html  css  js  c++  java
  • Lambda表达式树解析(下)包含自定义的provider和查询

    概述

      前面章节,总结了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,还需要研究......

    https://www.cnblogs.com/xibei666/p/6858299.html

  • 相关阅读:
    浙大数据结构课后习题 练习二 7-2 Reversing Linked List (25 分)
    浙大数据结构课后习题 练习二 7-2 一元多项式的乘法与加法运算 (20 分)
    浙大数据结构课后习题 练习一 7-1 Maximum Subsequence Sum (25 分)
    浙大数据结构课后习题 练习一 7-1 最大子列和问题 (20 分)
    PAT Basic 1019 数字黑洞 (20 分)
    PAT Basic 1017 A除以B (20 分)
    PAT Basic 1013 数素数 (20 分)
    PAT Basic 1007 素数对猜想 (20 分)
    PAT Basic 1003 我要通过! (20 分)
    自动化运维——HelloWorld(一)
  • 原文地址:https://www.cnblogs.com/sjqq/p/9505082.html
Copyright © 2011-2022 走看看