C#---Expression(表達式)

前言: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. 維…