在使用 ef 開中我們經常使用 xx.where(p=>p.name="張三") 查詢資料,之把能這樣是因為 ef 框架會把這些c#**轉成sql語句, 其中主要用到的就是表示式樹,今天就來學習一下表示式樹。
func func = (a, b) => a +b;上面分別是 func 委託和表示式樹,看上去很相似,左邊只多了 expression<> 右邊完全一樣,其實還是有很大區別的,對於委託我們只能傳遞引數來呼叫,內部的**在程式執行中是無從得知的,而表示式樹在這點上相反,表示式樹是一種資料結構,可以通過 c# **清晰的獲取內部的細節。expressionint,int,int>> expression = (a, b) => a + b;
上面的例子中是使用 lambda 為表示式樹賦值,其實還有另一種寫法
parameterexpression parametera = expression.parameter(typeof(int),"a"上面的例子對應於第一種寫法,第一種寫法是語法糖,其實編譯器最終生成還是這種**,可以通過反編譯軟體來驗證。);parameterexpression parameterb = expression.parameter(typeof(int),"b"
);binaryexpression binaryexpression =expression.add(parametera, parameterb);
expression
int, int, int>> expression = expression.lambdaint, int, int>>(binaryexpression,parametera,parameterb);
認識一下表示式樹的主要部分
body:表示式主體,例子中是二元表示式,常用的還有
nodetype:節點型別,例子中是 lambda ,常用還有的+,-,*,/,>,=,
parameters:表示式的引數,a 和 b
console.writeline(expression.body);輸出是console.writeline(expression.nodetype);
console.writeline(expression.parameters[
0]);
console.writeline(expression.parameters[
1]);
(a + b)
lambdaab
body 的型別是 expression,例子中的是二元表示式,所以要轉換成 binaryexpression 類來檢視資訊
binaryexpression binaryexpression =(binaryexpression)expression.body;輸出是aconsole.writeline(binaryexpression.left);
console.writeline(binaryexpression.right);
console.writeline(binaryexpression.nodetype);
badd
剛才是乙個簡單表示式,再來看兩個複雜點的,經過第一次解析後 left 和 right 就是第一種解析的表示式,可以把 left 和 right 再解析一次,最終完全解析,不管多複雜的表示式都可以像這樣解析出來
上面的例子只是為了了解表示式樹結構,用這種方法解析存在兩個問題
一是 binaryexpression 這裡固定了只能解析二元表示式,如果是其它表示式就會報錯
二是不知道需要解析多少層才解析完
要解析表示式樹要用 c# 裡的 expressionvisitor 類,這個類就是專門解析表示式樹的,它是乙個抽象類,需要建個類繼承它,使用過程如下,首先呼叫父類 visit 方法,在 visit 中會判斷表示式的型別是一元(對應visitunary)、二元(對應visitbinary),常量(對應visitconstant)、引數(對應visitparameter)等表示式,然後就會進對應的解析方法中支解析,比如二元表示式的解析方法就是 visitbinary,然後我們重寫 visitbinary
下面是使用 expressionvisitor 解析表示式樹的例子,這麼說並不完全對,解析**是 expressionvisitor 已經寫好的,我們做的只解析過程中加入一些自己的**而已
最後來實現乙個簡單的由表示式樹生成sql語句的功能
classmyvisitor : expressionvisitor
protected
override
expression visitbinary(binaryexpression node)
public
string
getsqlstring()
protected
override
expression visitconstant(constantexpression node)
else
return
base
.visitconstant(node);
}protected
override
expression visitparameter(parameterexpression node)
return
base
.visitparameter(node);
}protected
override
expression visitmember(memberexpression node)
public
string
expressiontypetosql(expressiontype expressiontype)}}
expressionbool>> expression = p=>p.name=="寫得有點亂,忘見諒張三"&&p.name!="李四"
;myvisitor myvisitor = new
myvisitor();
myvisitor.visit(expression);
console.writeline(myvisitor.getsqlstring());
表示式 表示式樹 表示式求值
總時間限制 1000ms 記憶體限制 65535kb 描述 眾所周知,任何乙個表示式,都可以用一棵表示式樹來表示。例如,表示式a b c,可以表示為如下的表示式樹 a b c 現在,給你乙個中綴表示式,這個中綴表示式用變數來表示 不含數字 請你將這個中綴表示式用表示式二叉樹的形式輸出出來。輸入輸入分...
Lambda表示式表示式樹
在c 3.0中,繼匿名方法之後出現了lambda 表示式,使表達更為簡潔 快捷。lambda 表示式使用lambda 運算子 來定義,語法如下 引數列表 lambda 運算子的左邊是輸入引數,定義lambda表示式的接收引數列表,右邊包含表示式或語句塊,表示將表示式的值或語句塊返回的值傳給左邊的引數...
C 表示式樹Expression
表示式相加 常量表示式 expression firstarg expression.constant 2 expression secondarg expression.constant 4 相加 expression addexpression expression.add firstarg,s...