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,还需要研究......

时间: 2024-08-01 10:46:52

Lambda表达式树解析(下)的相关文章

Lambda表达式树构建(上)

概述 Lambda是C#常用的语句,采用委托等方式,来封装真实的代码块.Lambda其实就是语法糖,是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量.它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式.常用的方法有Where.Select.SelectMany.Aggregate等:语法结构SomeList.Where(p=>p.property==value),其中SomeList基础

EntityFramework动态多条件查询与Lambda表达式树

          在常规的信息系统中, 我们有需要动态多条件查询的情况, 例如UI上有多个选择项可供用户选择多条件查询数据. 那么在.net平台Entity Framework下, 我们用Lambda表达式树如何实现, 这里我们需要一个PredicateBuilder的UML类图: 实现的代码是这样的: /// <summary> /// Enables the efficient, dynamic composition of query predicates. /// </summ

用lambda表达式树优化反射

本节重点不讲反射机制,而是讲lambda表达式树来替代反射中常用的获取属性和方法,来达到相同的效果但却比反射高效. 每个人都知道,用反射调用一个方法或者对属性执行SetValue和GetValue操作的时候都会比直接调用慢很多,这其中设计到CLR中内部的处理,不做深究.然而,我们在某些情况下又无法不使用反射,比如:在一个ORM框架中,你要将一个DataRow转化为一个对象,但你又不清楚该对象有什么属性,这时候你就需要写一个通用的泛型方法来处理,以下代码写得有点恶心,但不妨碍理解意思: //将Da

定义通用的可通过lambda表达式树来获取属性信息

我们一般获取某个类型或对象的属性信息均采用以下几种方法: 一.通过类型来获取属性信息 var p= typeof(People).GetProperty("Age");//获取指定属性 var ps = typeof(People).GetProperties();//获取类型的所有属性 二.通过实例来获取属性信息 People people = new People(); var pro = people.GetType().GetProperty("Age");

C# Lambda表达式详解,及Lambda表达式树的创建

最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介.优雅. Lambda表达式 "Lambda表达式"是一个匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量.它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式.所有Lambda表达式都使

C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using System.Linq.Expressions; namespace INPEXOne.LearnCS { class RefletLambdaDelegate { static object[] para

轻量级表达式树解析框架Faller

有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架"(3) 这3篇文章更多的是说明一种方法,一种思路,而代码比较少 在发出来之后也有些朋友互加了好友一起讨论 在经过一些时间的修改和优化后,就有了现在这个框架 目前这个框架实现了SqlServer和Oracle的解释 其他数据库1来是不熟2来没时间3来我更希望大家可以使用这个框架自己动手实现一个数据库的解析,非常

今夜我懂了Lambda表达式_解析

现在时间午夜十一点~ 此刻的我血脉喷张,异常兴奋:因为专注得学习了一把java,在深入集合的过程中发现好多套路配合Lambda表达式真的是搜椅子,so开了个分支,决定从"只认得",变为"我懂得" start: 先上一盘代码,对应来解析: /*我是一个接口*/ interface Rap{ void show(); //注意:虽然没有用abstract修饰方法,但它真是抽象方法,我特意去试了下,应该是没有方法体的方法默认在前面加abstract } /*我是二个接口*

JAVA8 Lambda表达式完全解析

JAVA8 新特性 在学习JAVA8 Lambda之前,必须先了解一下JAVA8中与Lambda相关的新特性,不然对于一些概念会感到比较陌生. 1. 接口的默认方法和静态方法 Java 8允许我们给接口添加一个默认方法,用default修饰即可.默认方法可以重写,也可以不用重写.这就是和抽象方法的区别,在用法上,没有其他区别. public interface IMyInterface { void onMethond(String str);//这是一个抽象方法 default String