5.3表达式树

5.3表达式树

表达式树对应Expression<TDelegate>类型,从Lambda表达式生成表达式树:

Expression<Func<Book,bool>> e=b=>b.Price>5;可以看到,编译器自动将Lambda表达式编译为Expression类型

Expression和Func的区别:Expression中存储了运算逻辑,而Func没有。简单来讲,Expression类似于代码,而Func类似于编译后的程序。

Func<Book, bool> f1 = b => b.Price > 5 || b.AuthorName.Contains("aaa");
Expression<Func<Book, bool>> e = b => b.Price > 5 || b.AuthorName.Contains("aaa");
Console.WriteLine(f1);
Console.WriteLine(e);

在这里插入图片描述

可以看出,Func输出结果中,只有参数和返回值,内部没有运算逻辑。而Expression中存储了运算逻辑,要使用EF Core必须使用带运算逻辑的Expression。

查看表达式树

  • 可以在调试的时候通过快速监视来查看表达式树
  • 可以NuGet安装ExpressionTreeToString,调用ToString扩展方法来输出表达式树结构的字符串
Console.WriteLine(e.ToString("Object notation", "C#"));

通过代码动态创建表达式树

构造如下表达式树Expression<Func<Book,bool>> e = b=>b.Pricce>5;

//创建b参数节点
ParameterExpression paramB = Expression.Parameter(typeof(Book), "b");
//创建访问b的属性操作节点
MemberExpression exprLeft = Expression.MakeMemberAccess(paramB, typeof(Book).GetProperty("Price"));
//创建对应5这个常量的节点,要写成5.0因为是double类型对应数据库表中的类型,要格外注意
ConstantExpression exprRight = Expression.Constant(5.0, typeof(double));
//创建对应大于符号的二元运算符节点,并把exprLeft和exprRight分别设定为左右节点
BinaryExpression exprBody = Expression.MakeBinary(ExpressionType.GreaterThan, exprLeft, exprRight);
//使用Lambda方法把exprBody放到一个表达式树节点中
Expression<Func<Book, bool>> expr1 = Expression.Lambda<Func<Book, bool>>(exprBody, paramB);
ctx.Books.Where(expr1).ToList();
Console.WriteLine(expr1.ToString("Object notation", "C#"));

如上创建表达式树太过复杂,可以使用ExpressionTreeToString提供的ToString(“Factory methods”, “C#”)直接输出代码,然后使用using static方法引入Expression类,进行简单的改写就可以生成,注意常量类型,要使用5.0形式。另外,对于double和int等基本类型相等的比较和对string等复杂类型的比较不一样,对于基本类型,调用的是Equal方法,对于复杂类型,则要调用==重载运算符的重载方法op_Equality。

//动态创建Expression表达式树,并且可传递参数
IEnumerable<Book> QueryBooks(string propName, object value)
{
	Type type = typeof(Book);
	PropertyInfo propInfo = type.GetProperty(propName);
	Type propType = propInfo.PropertyType;
	var b = Parameter(typeof(Book),"b");
	Expression<Func<Book,bool>> expr;
	if (propType.IsPrimitive)//如果是int、double等基本数据类型
	{
		expr = Lambda<Func<Book, bool>>(Equal(
				MakeMemberAccess(b,typeof(Book).GetProperty(propName)),
				Constant(value)),b);
	}
	else//如果是string等类型
	{
		expr = Lambda<Func<Book, bool>>(MakeBinary(ExpressionType.Equal,
				MakeMemberAccess(b,typeof(Book).GetProperty(propName)),
				Constant(value), false,propType.GetMethod("op_Equality")
			),b);
	}
	TestDbContext ctx = new TestDbContext();
	return ctx.Books.Where(expr).ToArray();
}

实现 Select的动态化

实现Select(b=>new{b.Id,b.Name})这种匿名类的动态化

using System.Linq.Expressions;
IEnumerable<object[]> Query<TEntity>(string[] propNames) where TEntity : class
{
    //创建参数节点
	ParameterExpression exParameter = Expression.Parameter(typeof(TEntity));
	List<Expression> exProps = new List<Expression>();//创建表达式集合
	foreach (string propName in propNames)
	{
		Expression exProp = Expression.Convert(Expression.MakeMemberAccess(
			exParameter,typeof(TEntity).GetProperty(propName)), typeof(object));
		exProps.Add(exProp);
	}
	Expression[] initializers = exProps.ToArray();//创建表达式数组
    //NewArrayExpression代表数组
	NewArrayExpression newArrayExp = Expression.NewArrayInit(typeof(object), initializers);
    //使用Lambda方法把NewArrayExpression放到一个表达式树节点中
	var selectExpression = Expression.Lambda<Func<TEntity, object[]>>(newArrayExp, exParameter);
	using TestDbContext ctx = new TestDbContext();
	IQueryable<object[]> selectQueryable = ctx.Set<TEntity>().Select(selectExpression);
	return selectQueryable.ToArray();
}

var items = Query<Book>(new string[] { "Id", "PubTime", "Title" });
foreach (object[] row in items)
{
	long id = (long)row[0];
	DateTime pubTime = (DateTime)row[1];
	string title = (string)row[2];
	Console.WriteLine(id + "," + pubTime + "," + title);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
《MATLAB在日常计算中的应用》由大量的MATLAB计算实例组成。通俗易懂,图文并茂,资料丰富,实用性强。提供大量MATLAB计算实例以及全部实例的M文件,方便读者使用。既适合初学者,也适合有一定MATLAB基础的爱好者或专业技术人员。 目录 第1章MATLAB基础知识 1.1MATLAB的发展历程 1.2MATLAB的特点 1.3MATLAB的桌面操作环境 1.4MATLAB的常量和变量 1.5MATLAB命令窗口应用例子 1.6小结 第2章多项式处理 2.1多项式的创建 2.2多项式的因式分解 2.3乘积展开成多项式 2.4合并同类项——对多项式合并同类项 2.5多项式加法(或减法) 2.6多项式乘法 2.7多项式除法 2.8求多项式的根 2.9多项式的替换 2.10符号简化 2.11分式通分 2.12求符号函数的反函数 2.13求符号表达式的复合运算 2.14将符号表达式转化为数值表达式 2.15将数值表达式转化为符号表达式 2.16小结 第3章MATLAB绘图 3.1二维绘图 3.1.1画函数图 3.1.2画饼状图 3.1.3画条形图 3.1.4手工绘图 3.1.5在极坐标下绘图 3.2三维绘图 3.2.1画球形图 3.2.2画圆柱体图 3.2.3画三维曲线图 3.2.4画直方图 3.2.5画饼状图 3.2.6画低通滤波器的三维网格图 3.2.7画三维平面图 3.2.8画瀑布图 3.2.9画伞状图 3.2.10画花蕊图 3.2.11画正立方体 3.3小结 第4章复数运算 4.1复数简介 4.1.1复数 4.1.2复数的四种表示形式 4.1.3复数的四则运算 4.1.4复数的其他运算 4.2复数运算程序1 4.2.1复数代数形式和极坐标形式间的相互转换程序 4.2.2求代数形式复数的倒数程序 4.2.3求任一复数平方根的程序 4.2.4求两个代数形式复数之积的程序 4.2.5求两个代数形式复数之商的程序 4.3复数运算程序2 4.3.1求复数的乘幂程序 4.3.2求复数的N次方根程序 4.3.3求复数的指数程序 4.3.4求复数的自然对数程序 4.3.5求复数的常用对数程序 4.3.6求复数的正弦程序 4.3.7求复数的余弦程序 4.3.8求复数的正切程序 4.4小结 第5章矩阵计算 5.1矩阵简介 5.1.1行列式 5.1.2矩阵的加法、乘法和矩阵的转置 5.1.3矩阵的除法——矩阵求逆 5.1.4矩阵的特征值和特征向量 5.2求行列式值 5.2.1求3阶行列式值 5.2.2求4阶行列式值 5.2.3求5阶行列式值 5.2.4求6阶行列式值 5.3矩阵转置 5.3.1将3阶矩阵转置 5.3.2将4阶矩阵转置 5.3.3将5阶矩阵转置 5.3.4将6阶矩阵转置 5.4矩阵相乘 5.4.1两个3阶实矩阵相乘 5.4.2两个4阶实矩阵相乘 5.4.3两个5阶实矩阵相乘 5.4.4一个4×5矩阵与一个5×3矩阵相乘 5.5矩阵求逆 5.5.1求2阶矩阵的逆阵 5.5.2求3阶矩阵的逆阵 5.5.3求4阶矩阵的逆阵 5.5.4求5阶矩阵的逆阵 5.5.5求6阶矩阵的逆阵 5.6求矩阵的特征值和特征向量 5.6.1求2阶矩阵的特征值和特征向量 5.6.2求3阶矩阵的特征值和特征向量 5.6.3求4阶矩阵的特征值和特征向量 5.7小结 第6章解多元一次线性方程组 6.1多元一次方程组简介 6.2解实系数多元一次方程组 6.2.1解实系数二元一次方程组 6.2.2解实系数三元一次方程组 6.2.3解实系数四元一次方程组 6.2.4解实系数五元一次方程组 6.2.5解实系数六元一次方程组 6.3解复系数多元一次方程组 6.3.1解复系数二元一次方程组 6.3.2解复系数三元一次方程组 6.3.3解复系数四元一次方程组 6.3.4解复系数五元一次方程组 6.3.5解复系数六元一次方程组 6.4小结 第7章解一元N次方程(上) 7.1实系数一元一次方程 7.2实系数一元二次方程 7.2.1实系数一元二次方程的求根公式介绍 7.2.2程序实例 7.3实系数一元三次方程 7.3.1卡尔丹公式 7.3.2盛金公式 7.3.3解题实例——解缺少二次项的实系数一元三次方程 7.3.4解题实例——解一般形式的实系数一元三次方程 7.4实系数一元四次方程 7.4.1一元四次方程解法介绍 7.4.2MATLAB解一元四次方程实例 7.5复系数一元一次方程 7.6复系数一元二次方程 7.6.1复系数一元二次方程解法介绍 7.6.2说明 7.6.3实例 7.7复系数一元三次方程 7.8复系数一元四次方程 7.9小结 第8章解一元N次方程(下) 8.1实系数一元代数方程 8.1.1求解实系数一元五次方程的根 8.1.2求解实系数一元六次方程的根 8.1.3求解实系数一元七次方程的根 8.1.4求解实系数一元八次方程的根 8.2复系数一元代数方程 8.2.1求解复系数一元五次方程的根 8.2.2求解复系数一元六次方程的根 8.2.3求解复系数一元七次方程的根 8.2.4求解复系数一元八次方程的根 8.3小结 第9章超越方程及非线性方程 9.1超越方程说明 9.2解超越方程 9.2.1解指数方程 9.2.2解对数方程 9.2.3解三角方程 9.2.4解无理方程 9.2.5解反三角函数方程 9.2.6解一般超越方程 9.3解非线性方程 9.3.1解一元非线性方程 9.3.2解二元非线性方程组 9.3.3解三元非线性方程组 9.4小结 第10章用图像法解实系数一元N次方程 10.1实系数一元一次方程 10.2实系数一元二次方程 10.3实系数一元三次方程 10.4实系数一元四次方程 10.5实系数一元五次方程 10.6实系数一元六次方程 10.7实系数一元七次方程 10.8实系数一元八次方程 10.9小结 第11章用图像法解实系数N元一次方程组 11.1实系数二元一次方程组 11.2实系数三元一次方程组 11.3实系数N元一次方程组 11.4小结 参考文献

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步、步、为营

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值