一、Expression是什么
1、和委托的区别
a、委托是编译时,表达式目录树是运行时,在应用程序运行过程中可以重新赋值
b、委托相当于是拿到别人dll文件,只能调用里面的方法;表达式目录树相当于拿到了别人的源码,可以进行扩展
2、Expression本质
a、表达式目录树是一个类的封装,描述了一个结构,有身体部分和参数部分
b、表达式目录树展开后的每一个节点也是一个表达式目录树
二、Expression动态拼接
1、最基础版本
Expression<Func<int>> expression = () => 123 + 456;ConstantExpression constant1= Expression.Constant(123,typeof(int));ConstantExpression constant2 = Expression.Constant(456, typeof(int));BinaryExpression binaryExpression =Expression.Add(constant1, constant2);Expression<Func<int>> expressionReslut = Expression.Lambda<Func<int>>(binaryExpression,Array.Empty<ParameterExpression>());Func<int> func = expressionReslut.Compile();var result = func.Invoke();
2、带参数版本
Expression<Func<int,int>> expression = m => m + 123;ParameterExpression parameterExpression =Expression.Parameter(typeof(int),\"m\");ConstantExpression constantExpression = Expression.Constant(123, typeof(int));BinaryExpression binaryExpression =Expression.Add(parameterExpression, constantExpression);Expression<Func<int,int>> expressionReslut = Expression.Lambda<Func<int,int>>(binaryExpression, new ParameterExpression[1]parameterExpression});Func<int,int> func = expressionReslut.Compile();var result = func.Invoke(10);
3、带有多个参数
Expression<Func<int, int, int>> expression = (m, n) => m * n + 2;ParameterExpression parameterExpressionM = Expression.Parameter(typeof(int), \"m\");ParameterExpression parameterExpressionN = Expression.Parameter(typeof(int), \"n\");BinaryExpression multiply = Expression.Multiply(parameterExpressionM, parameterExpressionN);ConstantExpression constantExpression = Expression.Constant(2);BinaryExpression plus = Expression.Add(multiply, constantExpression);Expression<Func<int, int, int>> expression1 = Expression.Lambda<Func<int, int, int>>(plus, new ParameterExpression[2{parameterExpressionM,parameterExpressionN});Func<int, int, int> func1 = expression1.Compile();int iResult1 = func1.Invoke(20, 30);
4、对象字段值比较
如果碰到很长的表达式目录树,建议先拼装右边,再拼装左边
Expression<Func<User, bool>> expression = (x) => x.Id.ToString() == \"1\" && x.Name.Equals(\"xiaohemiao\");// 1、声明参数ParameterExpression parameterExpression=Expression.Parameter(typeof(User),\"x\");// 2、因为要拼装x.Name,所以要先找到NamePropertyInfo propName = typeof(User).GetProperty(\"Name\");// 3、拼装x.NameMemberExpression memberExpression = Expression.Property(parameterExpression, propName);// 4、因为需要调用Equals,所以要先获取Equals方法MethodInfo methodInfo= typeof(string).GetMethod(\"Equals\",new Type[] { typeof(string)});// 5、调用Equals方法,x.Name.Equals(\"xiaohemiao\") ,调用需要“xiaohemiao”,所以先声明一个字符串常量ConstantExpression constantExpressionRight =Expression.Constant(\"xiaohemiao\", typeof(string));// 6、拼装x.Name.Equals(\"xiaohemiao\")MethodCallExpression MethodCallExpressionRight=Expression.Call(memberExpression, methodInfo, constantExpressionRight);// 7、开始拼装左边 拼装x.Id,所以先找到IdPropertyInfo propId = typeof(User).GetProperty(\"Id\");// 8、拼装x.IdMemberExpression memberExpressionId = Expression.Property(parameterExpression, propId);// 9、因为要拼装x.Id.ToString(),所以先找到ToString方法MethodInfo toString = typeof(int).GetMethod(\"ToString\", new Type[0] { });// 10、开始拼装x.Id.ToString()MethodCallExpression methodCallExpressionLeft1=Expression.Call(memberExpressionId, toString, Array.Empty<Expression>());// 11、需要声明一个常量ConstantExpression constantExpressionLeft= Expression.Constant(\"1\",typeof(string));// 12、拼装x.Id.ToString().Equals(\"1\"),需要调用Equals方法,先获取Equals方法--上面已经获取过,可以直接使用BinaryExpression BinaryExpression = Expression.Equal(methodCallExpressionLeft1, constantExpressionLeft);// 13、左边和右边都拼装好了,现在要把左边和右边 && 起来BinaryExpression binaryExpression=Expression.AndAlso(BinaryExpression, MethodCallExpressionRight);Expression<Func<User, bool>> expression1 = Expression.Lambda<Func<User, bool>>(binaryExpression, new ParameterExpression[1]{parameterExpression});Func<User, bool> func = expression1.Compile();var result = func.Invoke(new User() {Id=1,Name=\"xiaohemiao\"});