? ? Linq是.Net中非常強(qiáng)大的功能,特別是手機(jī)用進(jìn)行復(fù)雜查詢時候非常方便肿孵。有時候我們需要動態(tài)構(gòu)造lambda表達(dá)式毁渗,一種做法是使用Expression類中的Not、Call等方法構(gòu)建表達(dá)式樹按傅,如下創(chuàng)建的是?p?=>?!p.Name.Contains("小")這個lambda表達(dá)式的代碼:
ParameterExpression pParameterExpr = Expression.Parameter(typeof(People),"p");
var field = Expression.Property(pParameterExpr,
??????????????? typeof(People).GetProperty(nameof(People.Name)));
var contains =typeof(string).GetMethod(nameof(string.Contains));
var value = Expression.Constant("小",typeof(string));
var containsCall = Expression.Call(field, contains, newExpression[] { value });
var notContainsCall = Expression.Not(containsCall);
Expression> express1 =
??????????????? Expression.Lambda>(notContainsCall, pParameterExpr);
Console.WriteLine(express1);
? ? 這就是構(gòu)建了一棵表達(dá)式樹。
? ? 不過這種構(gòu)造表達(dá)式樹的方法特別麻煩胧卤,特別是要創(chuàng)建比較復(fù)雜的表達(dá)式樹的時候代碼量特別大唯绍,很容易寫錯,而且最好有編譯原理中AST(抽象語法樹)等的基本概念枝誊。
? ? 下面介紹一種簡單的創(chuàng)建表達(dá)式樹的方法况芒,可以直接根據(jù)lambda表達(dá)式字符串創(chuàng)建表達(dá)式樹。
? ? 首先通過Nuget安裝System.Linq.Dynamic包:
Install-Package System.Linq.Dynamic
? ? 然后代碼:
string linq = "!p.Name.Contains(\"小\")";
var p = Expression.Parameter(typeof(People), "p");//設(shè)定變量p的類型
LambdaExpression exp =System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, linq);
Console.WriteLine(exp);
? ? 當(dāng)然這種方式也有缺點(diǎn)叶撒,如果有比較多嵌套關(guān)系绝骚,特別是嵌套層次比較多的時候還要考慮括號的配對等問題耐版,這時候反正用傳統(tǒng)的方法創(chuàng)建反而更簡單。當(dāng)然由于ParseLambda返回的是Expression對象皮壁,也可以把兩種方法結(jié)合起來使用:
string linq1 = "p.Name.Contains(\"小\") and p.Age<5";
string linq2 = "p.Name.StartsWith(\"我\") or (p.Age>6 andp.Height<180)";
var p = Expression.Parameter(typeof(People), "p");
LambdaExpression expr1 =System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, linq1);
LambdaExpression expr2 =System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, linq2);
var expr3 = Expression.Not(Expression.AndAlso(expr1.Body,expr2.Body));//LambdaExpression拿出來用的時候一定要用它的Body
Console.WriteLine(expr3);