认识IQueryable和IQueryProvider接口

1.Func<Student, bool>和Expression<Func<Student, bool>>的区别

    class Program
    {
        static void Main(string[] args)
        {
            Func<Student, bool> func = t => t.Name == "1111";
            //匿名函数
            Expression<Func<Student, bool>> expression = t => t.Name == "1111";
            //表达式树 有Body Right、Left,Right里面又有Right、Left,它们的类型都是继承自 Expression 。这种节点下面有节点,可以无限附加下去的数据结构我们称为树结构数据。也就是我们的表达式树。          
            Console.Read();
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
        public string Sex { get; set; }
    }

2.解析表达式树

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace RedisTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<Student, bool>> expression = t => t.Name == "1111" && t.Name == "2222";
            AnalysisExpression.VisitExpression(expression);
            /*
            运算符:AndAlso
            运算符:Equal
            字段名称:Name,类型:System.String
            常量值:1111
            运算符:Equal
            字段名称:Name,类型:System.String
            常量值:2222
            */
            Console.Read();
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
        public string Sex { get; set; }
    }

    public static class AnalysisExpression
    {
        public static void VisitExpression(Expression expression)
        {
            switch (expression.NodeType)
            {
                case ExpressionType.Call://执行方法
                    MethodCallExpression method = expression as MethodCallExpression;
                    Console.WriteLine("方法名:" + method.Method.Name);
                    for (int i = 0; i < method.Arguments.Count; i++)
                        VisitExpression(method.Arguments[i]);
                    break;
                case ExpressionType.Lambda://lambda表达式
                    LambdaExpression lambda = expression as LambdaExpression;
                    VisitExpression(lambda.Body);
                    break;
                case ExpressionType.Equal://相等比较
                case ExpressionType.AndAlso://and条件运算
                    BinaryExpression binary = expression as BinaryExpression;
                    Console.WriteLine("运算符:" + expression.NodeType.ToString());
                    VisitExpression(binary.Left);
                    VisitExpression(binary.Right);
                    break;
                case ExpressionType.Constant://常量值
                    ConstantExpression constant = expression as ConstantExpression;
                    Console.WriteLine("常量值:" + constant.Value.ToString());
                    break;
                case ExpressionType.MemberAccess:
                    MemberExpression Member = expression as MemberExpression;
                    Console.WriteLine("字段名称:{0},类型:{1}", Member.Member.Name, Member.Type.ToString());
                    break;
                default:
                    Console.Write("UnKnow");
                    break;
            }
        }

    }
}

3.认识IQueryable和IQueryProvider接口

ElementType 代表当然这个Query所对应的类型
Expression 包含了我们当然Query所执行的所有查询或者是其它的操作
IQueryProvider则是负责处理上面的Expression的实现

IQueryProvider只有两个操作,CreateQuery和Execute分别有泛型版本和非泛型版本。 CreatQuery用于构造一个IQueryable<T>的对象,这个类其实没有任何实现,只是继承了IQueryable和IEnumrable接口。主要用于计算指定表达式目录树所表示的查询,返回的结果是一个可枚举的类型。 而Execute会执行指定表达式目录树所表示的查询,返回指定的结果。

4.实现自己的IQueryable<T>、IQueryProvider

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace RedisTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var aa = new MyQueryable<Student>();
            var bb = aa.Where(t => t.Name == "1234");
            var cc = bb.Where(t => t.Sex == "");
            var dd = cc.AsEnumerable();
            var ee = cc.ToList();
            //每次在执行 Where 查询操作符的时候都会把lambda转化为express存放在MyQueryable的Expression里
            //调用 AsEnumerable() 方法的时候并不会去实际取值(只是得到一个IEnumerable)[注意:在EF里面查询不要先取IEnumerable后滤筛,因为AsEnumerable()会生成查询全表的sql]
            //执行 ToList() 方法时才去真正调用迭代器 GetEnumerator() 取值
            //真正取值的时候,会去执行 IQueryProvider 中的 Execute 方法。(就是在调用这个方法的时候解析表达式数,然后执行取得结果)
            //我们看到真正应该办实事的 Execute  我们却让他返回默认值了。
        }
    }

    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
        public string Sex { get; set; }
    }

    public class MyQueryProvider : IQueryProvider
    {
        public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
        {
            return new MyQueryable<TElement>(expression);
        }

        public IQueryable CreateQuery(Expression expression)
        {
            throw new NotImplementedException();
        }

        public TResult Execute<TResult>(Expression expression)
        {
            return default(TResult);
        }

        public object Execute(Expression expression)
        {
            return new List<object>();
        }
    }
    public class MyQueryable<T> : IQueryable<T>
    {
        public MyQueryable()
        {
            _provider = new MyQueryProvider();
            _expression = Expression.Constant(this);
        }

        public MyQueryable(Expression expression)
        {
            _provider = new MyQueryProvider();
            _expression = expression;
        }
        public Type ElementType
        {
            get { return typeof(T); }
        }

        private Expression _expression;
        public Expression Expression
        {
            get { return _expression; }
        }

        private IQueryProvider _provider;
        public IQueryProvider Provider
        {
            get { return _provider; }
        }

        public IEnumerator GetEnumerator()
        {
            return (Provider.Execute(Expression) as IEnumerable).GetEnumerator();
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            var result = _provider.Execute<List<T>>(_expression);
            if (result == null)
                yield break;
            foreach (var item in result)
            {
                yield return item;
            }
        }
    }
}

 再一个例子

    class Program
    {
        static void Main(string[] args)
        {
            var DB = new wolf_testEntities();
            decimal aa = 0;
            ParameterExpression pExpression = Expression.Parameter(typeof(People));
            var getPropertyValue = Expression.Property(pExpression, typeof(People).GetProperty("Num"));
            ConstantExpression cExpression = Expression.Constant(aa);
            BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.GreaterThan, getPropertyValue, cExpression);
            Expression<Func<People, bool>> lambda = Expression.Lambda<Func<People, bool>>(bExpression, pExpression);
            //Expression Tree 的条件 x=>x.Num>0
            var bbb = DB.People.Where(lambda).ToList();
            Console.ReadLine();
        }
    }
原文地址:https://www.cnblogs.com/lgxlsm/p/6762520.html