前言:Expression 是C# 高级编程,表达式的应用场景有 ORM框架:Entity Framework,Dapper等,规则引擎:动态业务规则评估, 依赖注入:高级DI容器实现,测试框架:模拟和断言, 动态查询构建:根据用户输入构建查询 等等。 学习掌握Expression 对于构建动态逻辑的应用非常有帮助。

1.Expression 的由来

为了将Linq 查询语句转换成SQL语句,在其它外部服务器上执行。将代码是给计算机执行的指令序列到代码是可以通过分析,转换和解释的数据结构。
将代码表示为数据结构,表达式架起了编译时静态世界到运行时动态世界的桥梁。

2. Expression的常用语法

2.1 Expression 特点

知道了Expression的目的,就是为了表达代码的数据结构。那么表达式的很多特点跟代码的表述形式很相近。

在学习一门语法之前,要先学习语句,变量,常量,赋值, 参数, 算术运算, 条件语句,循环语句,方法,类,对象,成员调用,异常 等等。

Expression 的类型有 NodeType 有84 种之多大多提供了表述以上代码的形式。

这里举个例子说明:

例1:想要定义一个变量,并且为这个变量赋值,打印输出这个变量的值

ParameterExpression varExp = Expression.Variable(typeof(int), "i");ConstantExpression conExp = Expression.Constant(10, typeof(int));BinaryExpression assignExp = Expression.Assign(varExp, conExp);Expression lambda = Expression.Block(new[] { varExp }, assignExp, varExp);Expression<Func<int>> lambdaExp = Expression.Lambda<Func<int>>(lambda);Console.WriteLine(lambdaExp.Compile().Invoke());

既然知道了表达式的目的就是表述一段代码结构,那这段代码结构是可以被编译器编译成委托,然后被执行的。

Console.WriteLine(lambdaExp.Compile().Invoke());
  1. Expression 是所有表达式类型的基类。
  2. Expression 的类型能够编写的大多数代码结构
  3. 通过表达式语句块最终编译动态生成一个委托

2.3 Expression核心组件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;namespace Study01_Expression.Study1_Expression
{internal class _01_Expression{private static readonly Lazy<_01_Expression> _instance = new Lazy<_01_Expression>(() => new _01_Expression());public static _01_Expression Instance => _instance.Value;public void Test(){Study3();}/// <summary>/// 初识表达式的核心组件/// </summary>public void Study1(){// 1.表达式的基类: Expression// 2.参数表达式:ParameterExpression// 3.二元运算表达式:BinaryExpression// 4.常量表达式:ConsantExpression// 5 方法表达式:MethodCallExpression// 6.属性或字段表达式: MemberExpression// 7.Lambda表达式:LambdaExpressionStringBuilder stringBuilder = new StringBuilder();stringBuilder.Append("\r\n1.表达式的基类: Expression");stringBuilder.Append("\r\n2.参数表达式:ParameterExpression");stringBuilder.Append("\r\n3.二元运算表达式:BinaryExpression");stringBuilder.Append("\r\n4.常量表达式:ConsantExpression");stringBuilder.Append("\r\n5.方法表达式:MethodCallExpression");stringBuilder.Append("\r\n6.属性或字段表达式: MemberExpression");stringBuilder.Append("\r\n7.Lambda表达式:LambdaExpression");Console.WriteLine(stringBuilder.ToString());}/// <summary>/// 7类表达式的基本使用/// </summary>public void Study2(){// 1.基本元素的创建// 2.二元运算的基本使用// 3.成员表达式的基本使用// 4.控制流语句的使用// 5.Lambda 表达式的使用// 6.组合表达式的基本使用}/// <summary>/// 表达式基本原素的创建/// </summary>public void Study3(){//// 1.参数与常量//ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "X");//ConstantExpression constantExpression = Expression.Constant(10, typeof(int));//ConstantExpression constantExpression1 = Expression.Constant(10);//// 2.变量//ParameterExpression parameterExpression1 = Expression.Variable(typeof(int), "Name");//// 在Block中使用变量//BlockExpression blockExpression = Expression.Block(//    new[] { parameterExpression1 },//    Expression.Assign(parameterExpression1, Expression.Constant(5)),//    parameterExpression1//    );//Console.WriteLine(blockExpression.ToString());}/// <summary>/// 运算表达式方法/// </summary>public void Study4(){// 算术运算BinaryExpression binaryExpression = Expression.And(Expression.Constant(2), Expression.Constant(3));// 比较运算// =BinaryExpression binaryExpression1 = Expression.Equal(binaryExpression, Expression.Constant(4));// !=BinaryExpression binaryExpression2 = Expression.NotEqual(binaryExpression1, Expression.Constant(5));// >BinaryExpression binaryExpression3 = Expression.GreaterThan(binaryExpression1, binaryExpression2);// <BinaryExpression binaryExpression4 = Expression.LessThan(binaryExpression3, Expression.Constant(6));// 逻辑运算符// &BinaryExpression binaryExpression5 = Expression.Add(binaryExpression1, binaryExpression2);// |BinaryExpression binaryExpression6 = Expression.Or(binaryExpression5, binaryExpression4);// &&BinaryExpression binaryExpression7 = Expression.AndAlso(binaryExpression6, binaryExpression5);// || BinaryExpression binaryExpression8 = Expression.OrElse(binaryExpression6, binaryExpression7);// !UnaryExpression unaryExpression = Expression.Not(binaryExpression8);}/// <summary>/// 成员访问与方法调用/// </summary>public void Study5(){// 1.属性和字段的访问ParameterExpression param = Expression.Parameter(typeof(int), "X");Expression.Field(param, "_internalField");Expression.Property(param, "Length");// 静态成员的访问Expression.Property(null, typeof(DateTime), "Now");ParameterExpression personParam = Expression.Parameter(typeof(Persion), "P");// 2.方法的调用// p.SayHello("World");Expression.Call(personParam,typeof(Persion).GetMethod("SayHello"),Expression.Constant("World"));// string.Concat("Hello","","World");// 静态方法的调用Expression.Call(typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) }),Expression.Constant("Hello"),Expression.Constant(""),Expression.Constant("World"));}/// <summary>/// 对象的创建与初始化/// </summary>public void Study6(){NewExpression newExpression = Expression.New(typeof(Persion).GetConstructor(new[] { typeof(string), typeof(int) }),Expression.Constant("Join"),Expression.Constant(25));Persion persion = Expression.Lambda<Func<Persion>>(newExpression).Compile().Invoke();persion.SayHello("你好");}/// <summary>/// Expression构建表达式树/// </summary>public void Study7(){Expression<Func<int, int>> squareExpression = x => x * x;Console.WriteLine(squareExpression); // 输出 x => (x * x)// 编译并执行表达式树Func<int, int> func = squareExpression.Compile();int v = func.Invoke(5);Console.WriteLine(v);}/// <summary>/// 动态调用任意方法/// </summary>public void Study8(){Persion persion = new Persion("嘻嘻", 6);ConstantExpression constantExpression = Expression.Constant(persion);System.Reflection.MethodInfo? methodInfo = persion.GetType().GetMethod("SayHello");ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "str");MethodCallExpression methodCallExpression = Expression.Call(constantExpression, methodInfo, parameterExpression);Expression<Action<string>> expression = Expression.Lambda<Action<string>>(methodCallExpression, parameterExpression);expression.Compile().Invoke("你好");}}public class Persion{public string Name { get; set; }public int Age { get; set; }public Persion(string name, int age){Name = name;Age = age;}public void SayHello(string str){Console.WriteLine(string.Format("name{0},age{1},SayHello,{2}", Name, Age, str));}}
}

2.3 学习表达式的常见错误

变量的作用域在一个块内才有效,变量可以定义在作用域的外面。但是变量必须放在块内。
Lambda表达式的作用域对于 参数或者变量定义可以放在外面, 但是对于在body 内使用的参数或者变量,必须要在lambda 里面传入参数或者变量表达式对象。否则就会出现在此作用域内未定义的异常报错。

在这里插入图片描述
在lambda里面传入变量表达式实例参数。

  ParameterExpression jExp = Expression.Variable(typeof(int), "j");Expression<Func<int, int>> expression = Expression.Lambda<Func<int, int>>(Expression.Multiply(jExp, jExp),  //  参数 j 在此作用域内可见jExp);Console.WriteLine(expression.Compile().Invoke(10));

因为这里委托传入一个参数,但有时候不需要传入参数,但是想要使用参数表达式,又必须在Lmbda 的主体作用域范围里面有效,此时必须要借助表达式语句块来实现。

 Expression.Assign(jExp, Expression.Constant(5));BinaryExpression assign6 = Expression.Assign(jExp, Expression.Constant(6));BinaryExpression binaryExpression = Expression.Multiply(jExp, jExp);BinaryExpression binaryExpression1 = Expression.Assign(jExp, binaryExpression);BlockExpression blockExpression = Expression.Block(new[] { jExp }, assign6, binaryExpression, binaryExpression1, jExp);Expression<Func<int>> expression1 = Expression.Lambda<Func<int>>(blockExpression);Console.WriteLine(expression1.Compile().Invoke());

作用域这个对于初学者来说非常容易出错,这个点需要注意哦。

3. Expression和 委托的区别

表达式动态编译之后就是委托。
表达式描述可以根据代码逻辑动态构建代码结构,是动态的。
而委托是已经完成的,代表一个固定的代码片段。

4. Expression的使用场景

  • 依赖注入
    在依赖注入的框架的实现,是通过表达式来完成的,其中包括创建者,对注入的不同类型创建一个对象,然后为对象属性赋值,最后通过容器获取到这个对象,这里的实现过程通过表达式来实现的。
  • Linq多条件动态构建多条件查询 Where 里面就是一个委托,通过构建表达式分析生成 委托
  • ORM框架:Entity Framework,Dapper等 (这里暂时未遇到,等遇到再更新)
  • 对象属性映射

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96427.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96427.shtml
英文地址,请注明出处:http://en.pswp.cn/web/96427.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lodash-es 完整开发指南:ES模块化JavaScript工具库实战教程

简介 Lodash-es 是 Lodash 库的 ES 模块版本&#xff0c;提供了大量实用的 JavaScript 工具函数。它支持按需导入&#xff0c;可以显著减少打包体积&#xff0c;是现代 JavaScript 项目中的首选工具库。 主要特性 ES 模块支持: 完全支持 ES6 模块语法按需导入: 只导入需要的…

26. AI-Agent-Dify

文章目录前言一、Dify入门为什么使用 Dify&#xff1f;Dify 能做什么&#xff1f;二、Dify私有化部署Docker Compose 部署前提条件克隆 Dify 代码启动 Dify更新 Dify访问 Dify自定义配置三、Dify构建企业级Agent应用定义如何使用智能助手添加助手需要的工具配置 Agent配置对话开…

云原生:微服务与Serverless指南

Copilot时代的开发者效能提升 代码生成与补全&#xff1a;减少重复性编码工作&#xff0c;加快开发速度错误检测与修复&#xff1a;实时提示潜在问题&#xff0c;降低调试时间知识获取与学习&#xff1a;帮助开发者快速掌握新语言或框架协作效率&#xff1a;通过AI辅助减少团队…

SpringBoot + Apache Tika:一站式解决文件数据提取难题

在日常开发中&#xff0c;你是否也遇到过这样的窘境&#xff1a;领导甩来需求“把用户上传的 Word、Excel、PDF 里的关键信息扒出来存库”&#xff0c;你却要对着不同格式逐个攻坚——解析 Word 用 POI 还要处理 .doc/.docx 兼容&#xff0c;解析 Excel 要啃合并单元格、公式计…

车牌模拟生成器:Python3.8+Opencv代码实现与商业应用前景(C#、python 开发包SDK)

车牌模拟生成器&#xff1a;Python代码实现与商业应用前景引言在智慧城市建设和汽车行业数字化浪潮中&#xff0c;车牌作为车辆的唯一标识&#xff0c;其相关技术应用正变得越来越重要。今天我们将介绍一个基于Python的车牌模拟生成器&#xff0c;探讨其技术实现、功能特点以及…

小程序非主页面的数据动作关联主页面的数据刷新操作

如果在主页面跳转到其他页面。比如说我的收藏页面&#xff0c;然后有取消收藏的动作&#xff0c;当返回到主页面的时候&#xff0c;如果有关联数据显示在主页面&#xff0c;刷新页面对应的状态。 下面的代码是实现&#xff1a;//卡片收藏/取消if (newCollectd) {this.setData({…

后端(fastAPI)学习笔记(CLASS 1):扩展基础

一、python的类型声明1、类型声明的背景和作用python 3.6 版本引入了“类型提示”1、类型提示是一种新的语法&#xff0c;用来声明变量的类型2、提高编译器和工具的支持能力为什么要学习类型提示1、了解类型提示不仅仅对使用FastAPI有帮助&#xff0c;也能提高代码的可读性度和…

2023年系统分析师上半年论文试题分析

试题一 论信息系统的可行性分析信息系统可行性分析的目的是确认在当前条件下企业是否有必要建设新系统&#xff0c;以及建设新系统的工作是否具备必要的条件。如何进行可行性分析是系统分析师所必须面临的问题。请围绕信息系统可行性分析论题&#xff0c;依次从以下三个方面进行…

洛谷 P1967 [NOIP 2013 提高组] 货车运输(kruskal 重构树 + 求路径最小边权)

题目链接 题目难度 洛谷上是蓝题&#xff0c;本人认为评高了&#xff0c;此题思维和实现都不难&#xff0c;应该是绿题。 题目解法概括 kruskal 重构树 倍增优化求路径最小边权 代码 #include <iostream> #include <cstdio> #include <vector> #inclu…

【01】针对开源收银系统icepos (宝塔面板) 详细安装教程详细参考-优雅草卓伊凡

【01】针对开源收银系统icepos (宝塔面板) 详细安装教程详细参考-优雅草卓伊凡引言本文做参考&#xff0c;下篇文章 直接实践&#xff0c;由于已经选型本系统是服务端php开发的系统&#xff0c;他的系统环境如下&#xff1a;系统安装 环境要求ICEPOS对服务器或电脑硬件要求不高…

MySQL的常用命令

目录1. 连接MySQL数据库基本连接语法连接参数说明2. 数据库操作2.1 查看数据库2.2 创建数据库2.3 删除数据库3. 表操作3.1 查看表信息3.2 创建表3.3 常用数据类型3.4 修改表结构3.5 删除表4. 数据操作 (CRUD)4.1 插入数据 (CREATE)4.2 查询数据 (READ)基本查询条件查询排序和分…

Linux: config: CONFIG_CHECKPOINT_RESTORE;CRIU

文章目录 config CHECKPOINT_RESTORE commit related 简介 参考 如何使用 Checkpoint/Restore 功能 步骤 1:确保内核支持 步骤 2:安装 CRIU 步骤 3:检查点(Checkpoint) 步骤 4:恢复(Restore) 步骤 5:验证 常见应用场景 注意事项 python config CHECKPOINT_RESTORE bo…

eclipse怎么把项目设为web

在 Eclipse 中将一个项目设置为 Web 项目&#xff08;或称动态 Web 项目&#xff09;主要有两种场景&#xff1a;​创建新的 Web 项目​ 和 ​将现有项目转换为 Web 项目。我将为你详细讲解这两种方法。前提条件&#xff1a;确保你有必要的 Eclipse 组件在开始之前&#xff0c;…

CVPR 2025|基于视觉语言模型的零样本3D视觉定位

论文信息题目&#xff1a;Zero-Shot 3D Visual Grounding from Vision-Language Models基于视觉语言模型的零样本3D视觉定位作者&#xff1a;Rong Li, Shijie Li, Lingdong Kong, Xulei Yang, Junwei Liang论文创新点提出全新框架&#xff1a;论文提出SeeGround这一无需训练的零…

Realtime API 语音代理端到端接入全流程教程(含 Demo,延迟 280ms)

在现代应用中&#xff0c;实时语音交互已经成为重要功能&#xff0c;而低延迟的语音传输更是用户体验的关键指标。本文将详细介绍如何使用 Realtime API 实现 语音代理 的端到端接入&#xff0c;包括环境搭建、接口调用、低延迟优化及 Demo 演示。通过本教程&#xff0c;开发者…

AI赋能办公:用Python解决发票合并打印难题

一、问题的提出今天网友提问&#xff1a;报销时&#xff0c;财务要求要把发票合并打印&#xff0c;即两张合成一张放在A4纸上&#xff0c;中间还要加一道黑色分界线&#xff0c;如何快速完成数十张发票的打印&#xff1f;问题的提出二、问题分析这个问题可以采用两种方法解决&a…

Shell编程之正则表达式与文本处理工具

一、正则表达式基础1. 正则表达式概述​定义​&#xff1a;正则表达式&#xff08;Regular Expression&#xff0c;简称Regex&#xff09;是由普通字符​&#xff08;如字母、数字、标点符号&#xff09;与元字符​&#xff08;具有特殊含义的专用字符&#xff09;组成的字符串…

使用 Spring AI Alibaba Graph 实现工作流

1 依赖<dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter-dashscope</artifactId><version>1.0.0.2</version> </dependency><dependency><groupId>com.alibaba.cloud.…

碰一碰系统源码于小程序打通技术开发整合方案,驱动AI技术开发源代码

碰一碰系统结合小程序开发数据互通&#xff0c;驱动AI技术开发源代码碰一碰系统作为门店获客技术落地的核心载体&#xff0c;已从标准化产品向实体店定制演进。本文从源码d的形式出发&#xff0c;解析企业级数字人分身系统的交互系统&#xff0c;为技术团队提供可落地的开发指南…

深度学习——自然语言处理NLP

自然语言处理中的词向量技术演进与实践一、传统统计语言模型的困境与突破1.1 统计语言模型的局限性早期NLP主要依赖统计语言模型&#xff0c;如n-gram模型&#xff0c;通过统计词序列的频率来预测语言概率。这类模型存在两个根本缺陷&#xff1a;早期统计语言模型的局限性1. 维…