一、Lambda的介紹html
園中已經有不少關於lambda的介紹了。簡單來說就是vs編譯器給我帶來的語法糖,本質來說仍是匿名函數。在開發中,lambda給咱們帶來了不少的簡便。關於lambda的演變過程能夠看 Lambda的演變過程git
在這裏簡單的寫個lambda的寫法:github
Func<int, int, int> calculate = (x, y) => { return x + y; };//計算x+y的lambda
Console.WriteLine(calculate(1, 2).ToString());//輸出3
Console.WriteLine(calculate(2, 5).ToString());//輸出7sql
二、Lambda表達式樹:express
System.Linq.Expressions命名空間中包含了表明表達式的各個類,這些類都是繼承於Expression這個類,能夠經過Expression這個類的靜態方法來構建一些表達式樹。。表達式樹由三部分組成,左邊、操做類型、右邊 這三部分組成。ide
這樣就構成了一個簡單的表達式樹了。舉個栗子:函數
咱們構建一個輸入一個int類型的參數,判斷它是否是大於10的lambda表達式數,那麼左邊的表達式樹就是這個int類型的參數,操做類型就是「大於」,右邊表達式樹就是常量10.spa
ParameterExpression leftExpression = Expression.Parameter(typeof(int), "m");//int類型的,參數名稱爲m ConstantExpression rightExpression = Expression.Constant(10, typeof(int));//常量表達式樹,10 //進行左邊是否大於右邊的判斷 var binaryExpression =Expression.GreaterThan(leftExpression, rightExpression); Console.WriteLine(binaryExpression.ToString()); var lambda =Expression.Lambda<Func<int,bool>>(binaryExpression, leftExpression).Compile();//構建成lambda表達式 Console.WriteLine(lambda(5).ToString());
咱們再來構建一個輸入三個int類型的參數(a,b,c),先計算a+b,再判斷的(a+b)的值是否大於c的表達式樹。code
先分析下,htm
第一步咱們要計算a+b,那麼就要先構建一個a+b的表達式樹,在這步,左邊表達式樹是參數a,操做類型是「+」,右邊表達式樹是參數b。
第二步,將(a+b)的值與c比較,那麼左邊表達式樹就是第一步構建好的表達式樹,操做類型是">"的比較,右邊表達式數是參數c。
ParameterExpression left1Expression= Expression.Parameter(typeof(int), "a");//int類型的,參數名稱爲a ParameterExpression right1Expression = Expression.Parameter(typeof(int), "b");//int類型的,參數名稱爲b var aAndbExpression = Expression.Add(left1Expression, right1Expression);//進行相加拼接 ParameterExpression cExpression= Expression.Parameter(typeof(int), "c");//int類型的,參數名稱爲c var finallyExpression = Expression.GreaterThan(aAndbExpression, cExpression); Console.WriteLine(finallyExpression.ToString()); var finallyLambda= Expression.Lambda<Func<int,int,int, bool>>(finallyExpression, left1Expression, right1Expression, cExpression).Compile();//構建成lambda表達式 Console.WriteLine(finallyLambda(1, 6, 10).ToString());
簡單的構建表達式樹就講到這裏了。
三、根據lambda表達式樹生成對應sqlwhere條件
先簡單來拆分幾個簡單的lambda表達式樹
internal class User { public string Name { get; set; } public string Address { get; set; } public int Age { get; set; } public int Sex { get; set; } public bool IsDelete { get; set; } public DateTime? CreateTime { get; set; } }
a、Expression<Func<User, bool>> expression2 = m => m.Age == 10 && m.Age == 1;
這個表達式樹就是先判斷Age是否等於10,在判斷Age是否等於1,而後再對其結果進行與運算。分解以下:
1)、m.Age == 10:先是左邊是a.Age,這是一個MemberExpression(字段或者屬性表達式),表達式樹操做類型是==比較,右邊是10這個常量表達式樹
2)、與1相似
3)、將1和2的結果進行與運算
b、Expression<Func<User, bool>> expression2 = m => GetAge() ? m.Address == "" : m.Age == 1;
private static bool GetAge() { return false; }
這個表達式樹是先判斷GetAge方法返回的結果是true仍是false,true的話就在判斷Address是否等於空,false就判斷Age是否等於1
1)、GetAge();條件表達式樹()ConditionalExpression。
2)、m.Address == "",條件表達式樹判斷爲true執行的部分,
3)、m.Age == 1;條件表達式樹判斷爲false執行的部分,
就簡單的拆分這兩個表達式樹。
根據表達式樹生成對應的sqlWhere:
int[] ages = new int[] { 1, 2, 5, 67 }; Expression<Func<User, bool>> expression2 = m => (m.Age == 10 && m.Address.StartsWith("浙江") && m.Address.Contains("省") && m.Address.EndsWith("省")) || (m.Sex == 0 || "" == m.Address && ages.Contains(m.Age) && m.Age == ages[3]); //Expression<Func<User, bool>> expression2 = m => m.Address.TrimStart() == "11" && m.Name.TrimEnd() == "3434" && m.Age == 1 && m.IsDelete == true; //Expression<Func<User, bool>> expression2 = m => GetAge() ? m.Address == "" : m.Age == 1; //Expression<Func<User, bool>> expression2 = m => m.Age == 10 && m.Age == 1; SqlServerVisitor sqlVisitor = new SqlServerVisitor("A."); var sqlMember = sqlVisitor.GetSqlWhere(expression2.Body); Console.WriteLine(sqlMember.Item1); if (sqlMember.Item2 != null) { foreach (var item in sqlMember.Item2) { Console.WriteLine($"{item?.ParameterName},{item?.Value}"); } }
源碼下載:https://github.com/yjqGitHub/ExpressionResolve.git
若是有哪裏寫的不對的地方,還請指教,以避免我誤導了他人。