日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

什么是LambdaExpression,如何转换成Func或Action(2)

發(fā)布時(shí)間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 什么是LambdaExpression,如何转换成Func或Action(2) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
序言

  在上一篇中,我們認(rèn)識(shí)了什么是表達(dá)式樹、什么是委托,以及它們的關(guān)系。可能是我功力不好,貌似大家都不怎么關(guān)注,沒有講解出不同角度的問題。

  學(xué)習(xí)一種新技術(shù),是枯燥的過程,只有在你掌握后并能運(yùn)用時(shí)才能從它身上得到樂趣。

  做程序開發(fā)是一群很奇怪的人群,我們居然可以通過密密麻麻的英文字符加上標(biāo)點(diǎn)符號(hào)從中找到樂趣,確實(shí)很奇怪。

  考慮到大家接觸新技術(shù)需要一個(gè)過程:

其實(shí)對于很多人來說已經(jīng)不是新技術(shù)了,不過您會(huì)耐心看本篇后續(xù)的文章,說明您可能對這一項(xiàng)技術(shù)運(yùn)用的并不是很熟練

  所以我不打算一上來,就放一大堆代碼,然后解釋這是什么,那是什么,因?yàn)闀?huì)接觸很多新的關(guān)鍵詞,這樣大家學(xué)習(xí)起來會(huì)也會(huì)很痛苦

  本系列后面的所有篇幅都只在每篇中提一個(gè)新概念,這樣大家學(xué)習(xí)起來可以減少學(xué)習(xí)的范圍。

  然后也讓大家徹底搞懂每種類型的作用,同時(shí)我會(huì)用Lambda方式、動(dòng)態(tài)構(gòu)造、以及表達(dá)式樹的結(jié)構(gòu)三種方式來共同研究每篇課題的新類型。

什么是LambdaExpression

  LambdaExpression是繼承自Expression的。LambdaExpression的具體表現(xiàn)是:Expression<Func<>>或者Expression<Action<>>?

這段不明白沒關(guān)系,看下面示例就知道了

  首先,我們先從MSDN上看它的注釋說明:

描述一個(gè) lambda 表達(dá)式。 這將捕獲與 .NET 方法體類似的代碼塊。

  看MSDN注釋,我們還是沒搞懂它是什么意思,通俗的講:一段包含有運(yùn)算表達(dá)式的代碼,就是LambdaExpression。

  好吧,我說了吧,我的功底不行,您越看越不明白了………………(比MSDN解釋的還更糟糕)

LambdaExpression的定義 Expression<Func<int,int>> exp1 = o=> o + 1; Expression<Action<int>> exp2 = o=> o = 1 + 2;

  這種通過 o=> ...... 定義的就是LambdaExpression了。回過頭,我上面說的:

一段包含有運(yùn)算表達(dá)式的代碼,就是LambdaExpression。

  這樣子是不是更容易理解了?當(dāng)然上面只做了 加法操作,當(dāng)然不僅僅是這些操作,比如:

Expression<Func<UserVO, object>> exp = o => o.ID != 1 && (o.UserName == "steden" || o.UserName == "farseer.net")

  再比如在我們的Linq To Object中(當(dāng)然這里是純委托類型:Func<int,bool>,但它也是lambda表達(dá)式(注意不是表達(dá)式樹))

var lst = new List<int>(); lst.Where(o => o > 0);

  這些都是Lambda的定義。并且我們在上篇中也學(xué)習(xí)到如何將Expression<Func<UserVO,object>>轉(zhuǎn)換成Func<UserVO,object>。

LambdaExpression有什么用?

?  這時(shí)候聰明的讀者會(huì)想,即然我可以直接定義o=>.... ,為什么還要去理解LambdaExpression,反正C#編譯器會(huì)把它轉(zhuǎn)成LambdaExpression,根本不用我們關(guān)心。

?  確實(shí)是這樣,如果我們不需要?jiǎng)討B(tài)構(gòu)造它

我的意思是在程序運(yùn)行時(shí)動(dòng)態(tài)的生成它,則不是在編寫代碼的時(shí)候定義它?

  的時(shí)候,確實(shí)不用管是不是LambdaExpression了,只管在代碼上定義就行了。

  但是,其實(shí)很多場景下,我們是需要?jiǎng)討B(tài)的構(gòu)造它的,然后將它傳遞給其它地方,讓他們?nèi)ソ馕鏊?#xff0c;比如說:

?場景:在系統(tǒng)分層中,我們有個(gè)實(shí)體類,比如叫:UserVO(它屬于xxx.Entity類庫)。而在我們的底層中,需要?jiǎng)討B(tài)對實(shí)體類生成一些“通用的”操作(比如邏輯刪除功能)。但是我們知道底層是不知道上層有什么數(shù)據(jù)類型,甚至被誰調(diào)用了也不知道。因此這個(gè)時(shí)候,我就必須以動(dòng)態(tài)構(gòu)造的方式來創(chuàng)建它了。(因?yàn)槲腋静恢烙蠻serVO這個(gè)類)

  事實(shí)上,上面舉的場景例子不僅僅是LambdaExpression,其它的Expression也是如此。

  在講動(dòng)態(tài)構(gòu)造前,我覺得還是先讓大家學(xué)習(xí)如何解析它,必境我們的學(xué)習(xí)是先了解它的內(nèi)部結(jié)構(gòu),才更好的知道如何構(gòu)造它,不是嗎?

LambdaExpression的解析

  這要請出我們偉大的ExpressionVisitor類了。事實(shí)上,在我的Farseer.Net?ORM框架中重新封裝了這個(gè)類,叫AbsExpressionVisitor.cs,它是我所有表達(dá)式樹訪問器的基類,另外派出了一個(gè)專門提供給SQL的解析器,叫AbsSqlVisitor.cs

  其中有個(gè)入口方法:

protected virtual Expression Visit(Expression exp)

  ExpressionVisitor以訪問者模式(設(shè)計(jì)模式)來訪問這個(gè)表達(dá)式樹。可以看到有個(gè):exp.NodeType屬性,返回的是:ExpressionType枚舉:

protected virtual Expression Visit(Expression exp){if (exp == null) return exp; switch (exp.NodeType) { case ExpressionType.Negate: case ExpressionType.NegateChecked: case ExpressionType.Not: case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.ArrayLength: case ExpressionType.Quote: case ExpressionType.TypeAs: return this.VisitUnary((UnaryExpression)exp); case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.Subtract: case ExpressionType.SubtractChecked: case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.Divide: case ExpressionType.Modulo: case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.Or: case ExpressionType.OrElse: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.Equal: case ExpressionType.NotEqual: case ExpressionType.Coalesce: case ExpressionType.ArrayIndex: case ExpressionType.RightShift: case ExpressionType.LeftShift: case ExpressionType.ExclusiveOr: return this.VisitBinary((BinaryExpression)exp); case ExpressionType.TypeIs: return this.VisitTypeIs((TypeBinaryExpression)exp); case ExpressionType.Conditional: return this.VisitConditional((ConditionalExpression)exp); case ExpressionType.Constant: return this.VisitConstant((ConstantExpression)exp); case ExpressionType.Parameter: return this.VisitParameter((ParameterExpression)exp); case ExpressionType.MemberAccess: return this.VisitMemberAccess((MemberExpression)exp); case ExpressionType.Call: return this.VisitMethodCall((MethodCallExpression)exp); case ExpressionType.Lambda: return this.VisitLambda((LambdaExpression)exp); case ExpressionType.New: return this.VisitNew((NewExpression)exp); case ExpressionType.NewArrayInit: case ExpressionType.NewArrayBounds: return this.VisitNewArray((NewArrayExpression)exp); case ExpressionType.Invoke: return this.VisitInvocation((InvocationExpression)exp); case ExpressionType.MemberInit: return this.VisitMemberInit((MemberInitExpression)exp); case ExpressionType.ListInit: return this.VisitListInit((ListInitExpression)exp); default: throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType)); }

  然后根據(jù)傳入進(jìn)來的表達(dá)式樹,進(jìn)行一一解析,您能從中看到,當(dāng)case 到?ExpressionType.Lambda時(shí),會(huì)強(qiáng)制轉(zhuǎn)換成LambdaExpression

  并傳入VisitLambda方法中:

protected virtual Expression VisitLambda(LambdaExpression lambda){Expression body = this.Visit(lambda.Body);if (body != lambda.Body) { return Expression.Lambda(lambda.Type, body, lambda.Parameters); } return lambda; }

  事實(shí)上,這段代碼不用太過理解其它部份,只需要知道:

  當(dāng)Expression的NodeType ==?ExpressionType.Lambda時(shí),是可以顯示轉(zhuǎn)換成:LambdaExpression的。

  并且它有一個(gè)叫Body的屬性:(獲取 lambda 表達(dá)式的主體。),以及一個(gè)叫Parameters的屬性:(獲取 lambda 表達(dá)式的參數(shù)。

  Body返回的是LambdaExpression的主體

主體:指在LambdaExpression中的主要結(jié)構(gòu),或者說主要表達(dá)式。比如紅色標(biāo)記部份的:

o => o.ID != 1 && (o.UserName == "steden" || o.UserName == "farseer.net")

  而Parameters的返回的是參數(shù)表達(dá)式樹(出現(xiàn)了一個(gè)新名詞,下篇會(huì)詳細(xì)講解)。這里簡單的講解:上面出現(xiàn)的o 即是參數(shù),o的類型是UserVO

?  接著上面的:VisitLambda方法里繼續(xù)訪問:this.Visit(lambda.Body),也就是解析主體部份

  從上面的表達(dá)式代碼(紅色部份),它會(huì)執(zhí)行:this.VisitBinary((BinaryExpression)exp);方法。

  在這里知道BinaryExpression(表示包含二元運(yùn)算符的表達(dá)式。)是對于上面的&&的解析就足夠了。

  在上篇我們強(qiáng)調(diào)了Expression是一種數(shù)據(jù)結(jié)構(gòu),也就是說紅色部份,我們定義的代碼實(shí)質(zhì)是被保存成一種數(shù)據(jù)結(jié)構(gòu)的,如圖:

?  

  紅色底是:BinaryExpression類型(表示包含二元運(yùn)算符的表達(dá)式。)二元運(yùn)算,比如 && || >= < !=

  藍(lán)色底是:ParameterExpression類型(表示命名的參數(shù)表達(dá)式。)傳入的參數(shù),比如UserVO實(shí)體類

  綠色底是:ConstantExpression類型(表示具有常量值的表達(dá)式。)具體的常量值。

轉(zhuǎn)載于:https://www.cnblogs.com/kk-home/p/9249643.html

總結(jié)

以上是生活随笔為你收集整理的什么是LambdaExpression,如何转换成Func或Action(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。