基於Expression Lambda表達式樹的通用複雜動態查詢構建器——《構思篇二》已開源

来源:https://www.cnblogs.com/ls0001/archive/2023/05/27/ExpressionBuilder-3.html
-Advertisement-
Play Games

如果你有 *n* 個緩存伺服器,一個常見的負載均衡方式是使用以下的哈希方法: *伺服器索引 = 哈希(鍵) % N*,其中 *N* 是伺服器池的大小。 讓我們通過一個例子來說明這是如何工作的。如表5-1所示,我們有4台伺服器和8個字元串鍵及其哈希值。 ![image-2023052022160981 ...


接續[上篇之預告]

本篇來講講,如何根據前面設計的查詢描述器構造出可執行的表達式。正如標題所示,實現手段將採用Expression Lambda技術。

先來看看主角System.Linq.Expressions.Expression 長什麼樣,都有些什麼東西,能做什麼。 先看看它的類圖:

 

 

我們主要使用Expression這個類,它包含各種節點類型的 static工廠方法。特別是以下這些方法,對應了查詢需要用到的邏輯、比較、數學,等各種運算操作。

邏輯運算  
AndAlso(Expression, Expression) 表示And邏輯運算
OrElse(Expression, Expression) 表示Or邏輯運算
比較運算  
LessThan(Expression, Expression) 表示小於:"<"
LessThanOrEqual(Expression, Expression) 表示大於等於:“<="
GreaterThan(Expression, Expression) 表示大於:”>“
GreaterThanOrEqual(Expression, Expression) 表示大等於:”>="
Equal(Expression, Expression) 表示等於:”=“
NotEqual(Expression, Expression) 表示不等於:”!="
IsTrue(Expression) 測試表達式結果是否為“True"
IsFalse(Expression) 測試表達式結果是否為“False"
Not(Expression) 表示”Not"
數學運算  
Add(Expression, Expression) 加法
Subtract(Expression, Expression) 減法
Multiply(Expression, Expression) 乘法
Divide(Expression, Expression) 除法
Modulo(Expression, Expression) 模除
Power(Expression, Expression) 冪運算
一些操作  
Parameter(Type) 包裝一個類型為Type的參數
Call(Expression, MethodInfo, Expression, Expression) 包裝一個方法調用
Bind(MemberInfo, Expression) 包裝一個成員綁定,(屬性或欄位)
Quote(Expression) 包裝一個括弧
MakeUnary(ExpressionType, Expression, Type) 包裝一個一元運算
MakeBinary(ExpressionType, Expression, Expression) 包裝一個二元運算
TypeAs(Expression, Type) 包裝一個顯式引用或裝箱轉換,其中如果轉換失敗則提供“null”。
Coalesce(Expression, Expression, LambdaExpression) 包裝表示給定轉換函數的聚結操作。
變數、常量、欄位、屬性  
Default(Type) 包裝一個指定類型的預設值
Constant(Object, Type) 包裝一個常量
Assign(Expression, Expression) 賦值操作
Variable(Type, String) 包裝一個變數定義
Property(Expression, MethodInfo) 包裝一個屬性
Field(Expression, FieldInfo) 包裝一個欄位
PropertyOrField(Expression, String) 包裝一個指定名稱的欄位或屬性
要的就是這結果  
Lambda(Expression, ParameterExpression[]) 包裝一個委托,帶有一個參數表達式數組。

以上僅列出了一部分,它涵蓋了全部可能要使用到的函數,語句,欲詳細瞭解可以直接乘坐火箭到微軟官方網站查看。

這此函數或功能是有了,如何使用呢?來看個例子:將SQL:Table1.A > 5 and Table1.B=3,轉成(Table1)=>Table1.A > 5 && Table1.B==3;

Expression的世界里一切都是Expression。因此首先要將Table1A5B3先包裝成Expression

  • 開乾之前先談個對象
//實體類:
    public class Table
    {
        public int A;
        public int B;
    }

 

  • 然後包裝各種Expression
​
    //將Table1包裝成ParameterExpression:
    var p=Expression.Parameter(typeof(Table1),"Table1");
​
    //將5、3這兩個常量包裝成ConstantExpression:
    var num5=Expression.Constant(5,typeof(int));
    var num3=Expression.Constant(3,typeof(int));
​
    //將兩個屬性包裝成MemberExpression。
    var a=Expression.PropertyOrField(p,"A")
    var b=Expression.PropertyOrField(p,"B")
​
    //構造Table1.A>5:
    var gt=Expression.GreaterThen(a,num5); 
    //構造Table1.A=3:
    var eq=Expression.Equal(b,num3);    
    
​

 

  • 再構造兩個比較式
   //構造Table1.A>5:
   var gt=Expression.GreaterThen(a,num5); 
    //構造Table1.A=3:
    var eq=Expression.Equal(b,num3);    

 

  •  加上邏輯And將兩個比較式連接起來
    //構造Table1.A>5 && Table1.A=3
    var exp=Expression.AndAlso(gt,eq);

 

  •  結果就要出來了
//結果就獲得了:
    var lambda=Expression.Lambda()
        

 

  • 來來來,測試一下康康接果:
    /*===============來來來,測試一下:===============*/    
    var f=lambda.Compile();
    var x=f.DynamicInvoke(new Table(){A=6,B=3});
    var y = f.DynamicInvoke(new Table() { A = 2, B = 3 });
    Console.WriteLine("x:{0}\ny:{1}",x,y);
    Console.WriteLine("Lambda:{0}",lambda.ToString());          
    /*輸出:
    結果對嗎?我也不知道,我擼得這麼辛苦,先讓電腦休息一下,各位看官只要Ctrl+C,Ctrl+V就可以看到了.
    */

 

  • OK,其它各種操作,只要依葫蘆畫瓢便大功可成! 先爽一下!
  • 好,暫且爽到這裡,欲看如何把括弧弄成俄羅斯套娃,且看下回分解.
  • 隨手點個贊,讓我也爽爽,可好!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一說到創建桌面應用,就不得不提及Electron和Tauri框架。這次給大家主要分享的是基於electron最新版本整合vite4.x構建vue3桌面端應用程式。 之前也有使用vite2+vue3+electronc創建桌面端項目,不過 vue-cli-plugin-electron-builder ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、小票列印 目前市面上的小票印表機大多採用的列印指令集為ESC/POS指令,它可以使用ASCII碼、十進位、十六進位來控制列印,我們可以使用它來控制字體大小、列印排版、字體加粗、下劃線、走紙、切紙、控制錢箱等,下麵以初始化印表機為例: ...
  • apply(thisArg) apply(thisArg, argsArray) thisArg 在 func 函數運行時使用的 this 值。請註意,this 可能不是該方法看到的實際值:如果這個函數處於非嚴格模式下,則指定為 null 或 undefined 時會自動替換為指向全局對象,原始值會 ...
  • 具體的加密演算法可以可自行查詢其區別,這裡只是拋磚引玉,大部分加密方法基本都能通過改變傳入參數來實現。 C#相關類文檔: System.Security.Cryptography 命名空間 | Microsoft Learn Node JS相關文檔:Crypto | Node.js v16.20.0 ...
  • >我們是[袋鼠雲數棧 UED 團隊](http://ued.dtstack.cn/),致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。。 >本文作者:琉易 [liuxianyu.cn](https://link.juejin.cn/?target=h ...
  • # JavaScript 格式化金額 ## 一、[使用 `Intl.NumberFormat` 構造函數](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberForm ...
  • > 隨著人工智慧技術的不斷發展,阿裡體育等IT大廠,推出的“樂動力”、“天天跳繩”AI運動APP,讓**雲上運動會、線上運動會、健身打卡、AI體育指導**等概念空前火熱。那麼,能否將這些在APP成功應用的場景搬上小程式,分享這些概念的紅利呢?本系列文章就帶您一步一步從零開始開發一個AI運動小程式,本 ...
  • 前端構建的提速是一項比較複雜且細節的工程, 目前產品上在持續跟蹤構建慢的應用, 努力優化編譯速度, 但前端本身擁有一個比較自由的技術環境, 沒有統一的構建工具與流程, 另外語言本身的執行效率、單線程的構建也不好讓編譯機發揮其最大能力, 所以目前全局的通用優化手段還是會比較局限, 還是依賴項目自身的優... ...
一周排行
    -Advertisement-
    Play Games
  • 一、openKylin簡介 openKylin(開放麒麟) 社區是在開源、自願、平等和協作的基礎上,由基礎軟硬體企業、非營利性組織、社團組織、高等院校、科研機構和個人開發者共同創立的一個開源社區,致力於通過開源、開放的社區合作,構建桌面操作系統開源社區,推動Linux開源技術及其軟硬體生態繁榮發展。 ...
  • 簡介 Flurl是一個用於構建基於HTTP請求的C#代碼的庫。它的主要目的是簡化和優雅地處理網路請求(只用很少的代碼完成請求)。Flurl提供了一種簡單的方法來構建GET、POST、PUT等類型的請求,以及處理響應和異常。它還提供了一些高級功能,如鏈式調用、緩存請求結果、自動重定向等。本文將介紹Fl ...
  • 一:背景 1. 講故事 最近也挺奇怪,看到了兩起 CPU 爆高的案例,且誘因也是一致的,覺得有一些代表性,合併分享出來幫助大家來避坑吧,閑話不多說,直接上 windbg 分析。 二:WinDbg 分析 1. CPU 真的爆高嗎 這裡要提醒一下,別人說爆高不一定真的就是爆高,我們一定要拿數據說話,可以 ...
  • 剛開始寫文章,封裝Base基類的時候,添加了trycatch異常塊,不過當時沒有去記錄日誌,直接return了。有小伙伴勸我不要吃了Exception 其實沒有啦,項目剛開始,我覺得先做好整體結構比較好。像是蓋樓一樣。先把樓體建造出來,然後再一步一步的美化完善。 基礎的倉儲模式已經ok,Autofa ...
  • 框架目標 什麼是框架,框架能做到什麼? 把一個方向的技術研發做封裝,具備通用性,讓使用框架的開發者用起來很輕鬆。 屬性: 通用性 健壯性 穩定性 擴展性 高性能 組件化 跨平臺 從零開始-搭建框架 建立項目 主鍵查詢功能開發 綁定實體 一步一步的給大家推導: 一邊寫一邊測試 從零開始--搭建框架 1 ...
  • 大家好,我是沙漠盡頭的狼。 本方首發於Dotnet9,介紹使用dnSpy調試第三方.NET庫源碼,行文目錄: 安裝dnSpy 編寫示常式序 調試示常式序 調試.NET庫原生方法 總結 1. 安裝dnSpy dnSpy是一款功能強大的.NET程式反編譯工具,可以對.NET程式進行反編譯,代替庫文檔的功 ...
  • 在`Windows`操作系統中,每個進程的虛擬地址空間都被劃分為若幹記憶體塊,每個記憶體塊都具有一些屬性,如記憶體大小、保護模式、類型等。這些屬性可以通過`VirtualQueryEx`函數查詢得到。該函數可用於查詢進程虛擬地址空間中的記憶體信息的函數。它的作用類似於`Windows`操作系統中的`Task... ...
  • 背景介紹 1,最近有一個大數據量插入的操作入庫的業務場景,需要先做一些其他修改操作,然後在執行插入操作,由於插入數據可能會很多,用到多線程去拆分數據並行處理來提高響應時間,如果有一個線程執行失敗,則全部回滾。 2,在spring中可以使用@Transactional註解去控制事務,使出現異常時會進行 ...
  • 線程(thread)是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際 運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以併發多個線程,每條線 程並行執行不同的任務。 ...
  • 發現Java 21的StringBuilder和StringBuffer中多了repeat方法: /** * @throws IllegalArgumentException {@inheritDoc} * * @since 21 */ @Override public StringBuilder ...