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(); } }