表達式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)

      網(wǎng)友投稿 720 2025-03-31

      目錄


      表達式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)

      1. 訪問屬性

      2. 調(diào)用函數(shù)

      一,定義變量

      二,訪問變量/類型的屬性字段和方法

      三,實例化引用類型

      四,實例化泛型類型于調(diào)用

      五,定義集合變量、初始化、添加元素

      表達式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)

      一,定義變量

      C# 表達式樹中,定義一個變量,使用?ParameterExpression。

      表達式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)

      創(chuàng)建變量結(jié)點的方法有兩種,

      Expression.Parameter()Expression.Variable()//?另外,定義一個常量可以使用?Expression.Constant()。

      兩種方式都是生成?ParameterExpression?類型?Parameter()?和?Variable()?都具有兩個重載。他們創(chuàng)建一個 ParameterExpression節(jié)點,該節(jié)點可用于標識表達式樹中的參數(shù)或變量。

      對于使用定義:

      Expression.Variable?用于在塊內(nèi)聲明局部變量。

      Expression.Parameter用于聲明輸入值的參數(shù)。

      先看第一種

      public?static?ParameterExpression?Parameter(Type?type) ????????{????????????return?Parameter(type,?name:?null); ????????}???????? ????????????????public?static?ParameterExpression?Variable(Type?type) ????????{????????????return?Variable(type,?name:?null); ????????}

      從代碼來看,沒有區(qū)別。

      再看看具有兩個參數(shù)的重載

      public?static?ParameterExpression?Parameter(Type?type,?string?name) ????????{ ????????????Validate(type,?allowByRef:?true); ????????????bool?byref?=?type.IsByRef; ????????????if?(byref) ????????????{????????????????type?=?type.GetElementType(); ????????????}????????????return?ParameterExpression.Make(type,?name,?byref); ????????}

      public?static?ParameterExpression?Variable(Type?type,?string?name) ????????{????????????Validate(type,?allowByRef:?false);????????????return?ParameterExpression.Make(type,?name,?isByRef:?false); ????????}

      如你所見,兩者只有一個 allowByRef 出現(xiàn)了區(qū)別,Paramter 允許 Ref, Variable 不允許。

      從字面意思來看,聲明一個變量,應(yīng)該用Expression.Variable, 函數(shù)的傳入?yún)?shù)應(yīng)該使用Expression.Parameter。

      無論值類型還是引用類型,都是這樣子定義。

      二,訪問變量/類型的屬性字段和方法

      訪問變量或類型的屬性,使用

      Expression.Property()

      訪問變量/類型的屬性或字段,使用

      Expression.PropertyOrField()

      訪問變量或類型的方法,使用

      Expression.Call()

      訪問屬性字段和方法

      Expression.MakeMemberAccess

      他們都返回一個 MemberExpression類型。

      使用上,根據(jù)實例化/不實例化,有個小區(qū)別,上面說了變量或類型。

      意思是,已經(jīng)定義的值類型或?qū)嵗囊妙愋停亲兞浚?/p>

      類型,就是指引用類型,不需要實例化的靜態(tài)類型或者靜態(tài)屬性字段/方法。

      上面的解釋不太嚴謹,下面示例會慢慢解釋。

      1. 訪問屬性

      使用?Expression.Property()?或?Expression.PropertyOrField()調(diào)用屬性。

      Console 是一個靜態(tài)類型,Console.Title 可以獲取編譯器程序的實際位置。

      Console.WriteLine(Console.Title);

      使用表達式樹表達如下

      MemberExpression?member?=?Expression.Property(null,?typeof(Console).GetProperty("Title")); ????????????Expression>?lambda?=?Expression.Lambda>(member);????????????string?result?=?lambda.Compile()(); ????????????Console.WriteLine(result); ????????????Console.ReadKey();

      因為調(diào)用的是靜態(tài)類型的屬性,所以第一個參數(shù)為空。

      第二個參數(shù)是一個 PropertyInfo 類型。

      C#代碼如下

      List?a?=?new?List()?{?1,?2,?3?};????????????int?result?=?a.Count; ????????????Console.WriteLine(result); ????????????Console.ReadKey();

      在表達式樹,調(diào)用實例的屬性

      ParameterExpression?a?=?Expression.Parameter(typeof(List),?"a"); ????????????MemberExpression?member?=?Expression.Property(a,?"Count"); ????????????Expression,?int>>?lambda?=?Expression.Lambda,?int>>(member,?a);????????????int?result?=?lambda.Compile()(new?List?{?1,?2,?3?}); ????????????Console.WriteLine(result); ????????????Console.ReadKey();

      除了 Expression.Property() ,其他的方式請自行測試,這里不再贅述。

      2. 調(diào)用函數(shù)

      使用?Expression.Call()?可以調(diào)用一個靜態(tài)類型的函數(shù)或者實例的函數(shù)。

      以 Console 為例,調(diào)用 WriteLine() 方法

      Console.WriteLine("調(diào)用WriteLine方法"); ????????????MethodCallExpression?method?=?Expression.Call(????????????????null,????????????????typeof(Console).GetMethod("WriteLine",?new?Type[]?{?typeof(string)?}), ????????????????Expression.Constant("調(diào)用WriteLine方法")); ????????????Expression?lambda?=?Expression.Lambda(method); ????????????lambda.Compile()(); ????????????Console.ReadKey();

      Expression.Call() 的重載方法比較多,常用的重載方法是

      public?static?MethodCallExpression?Call(Expression?instance,?MethodInfo?method,?params?Expression[]?arguments)

      因為要調(diào)用靜態(tài)類型的函數(shù),所以第一個 instance 為空(instance英文意思是實例)。

      第二個 method 是要調(diào)用的重載方法。

      最后一個 arguments 是傳入的參數(shù)。

      寫一個類

      public?class?Test ????{ ????????public?void?Print(string?info) ????????{ ????????????Console.WriteLine(info); ????????} ????}

      調(diào)用實例的 Printf() 方法

      Test?test?=?new?Test(); ????????????test.Print("打印出來"); ????????????Console.ReadKey();

      表達式表達如下

      ParameterExpression?a?=?Expression.Variable(typeof(Test),?"test"); ????????????MethodCallExpression?method?=?Expression.Call( ????????????????a,????????????????typeof(Test).GetMethod("Print",?new?Type[]?{?typeof(string)?}), ????????????????Expression.Constant("打印出來") ????????????????); ????????????Expression>?lambda?=?Expression.Lambda>(method,a); ????????????lambda.Compile()(new?Test()); ????????????Console.ReadKey();

      注意的是,Expression.Variable(typeof(Test), "test");?僅定義了一個變量,還沒有初始化/賦值。對于引用類型來說,需要實例化。

      上面的方式,是通過外界實例化傳入里面的,后面會說如何在表達式內(nèi)實例化。

      三,實例化引用類型

      引用類型的實例化,使用 new ,然后選擇調(diào)用合適的構(gòu)造函數(shù)、設(shè)置屬性的值。

      那么,根據(jù)上面的步驟,我們分開討論。

      使用?Expression.New()來調(diào)用一個類型的構(gòu)造函數(shù)

      他有五個重載,有兩種常用重載:

      public?static?NewExpression?New(ConstructorInfo?constructor); ?public?static?NewExpression?New(Type?type);

      依然使用上面的 Test 類型

      NewExpression?newA?=?Expression.New(typeof(Test));

      默認沒有參數(shù)的構(gòu)造函數(shù),或者只有一個構(gòu)造函數(shù),像上面這樣調(diào)用。

      如果像指定一個構(gòu)造函數(shù),可以

      NewExpression?newA?=?Expression.New(typeof(Test).GetConstructor(xxxxxx));

      這里就不詳細說了。

      實例化一個構(gòu)造函數(shù)的同時,可以給屬性賦值。

      public?static?MemberInitExpression?MemberInit(NewExpression?newExpression,?IEnumerable?bindings);????????public?static?MemberInitExpression?MemberInit(NewExpression?newExpression,?params?MemberBinding[]?bindings);

      兩種重載是一樣的。

      我們將 Test 類改成

      public?class?Test ????{????????public?int?sample?{?get;?set;?}????????public?void?Print(string?info)????????{ ????????????Console.WriteLine(info); ????????} ????}

      然后

      var?binding?=?Expression.Bind(????????????????typeof(Test).GetMember("sample")[0], ????????????????Expression.Constant(10) ????????????);

      Expression.MemberInit()

      表示調(diào)用構(gòu)造函數(shù)并初始化新對象的一個或多個成員。

      如果實例化一個類,可以使用

      NewExpression?newA?=?Expression.New(typeof(Test)); ????????????MemberInitExpression?test?=?Expression.MemberInit(newA,????????????????new?List()?{?} ????????????????);

      如果要在實例化時給成員賦值

      NewExpression?newA?=?Expression.New(typeof(Test));????????????//?給?Test?類型的一個成員賦值 ????????????var?binding?=?Expression.Bind(????????????????typeof(Test).GetMember("sample")[0],Expression.Constant(10)); ????????????MemberInitExpression?test?=?Expression.MemberInit(newA,????????????????new?List()?{?binding} ????????????????);

      實例化一個類型,調(diào)用構(gòu)造函數(shù)、給成員賦值,示例代碼如下

      //?調(diào)用構(gòu)造函數(shù) ????????????NewExpression?newA?=?Expression.New(typeof(Test));????????????//?給?Test?類型的一個成員賦值 ????????????var?binding?=?Expression.Bind(????????????????typeof(Test).GetMember("sample")[0],?Expression.Constant(10));????????????//?實例化一個類型 ????????????MemberInitExpression?test?=?Expression.MemberInit(newA,????????????????new?List()?{?binding?} ????????????????);????????????//?調(diào)用方法 ????????????MethodCallExpression?method1?=?Expression.Call( ????????????????test,????????????????typeof(Test).GetMethod("Print",?new?Type[]?{?typeof(string)?}), ????????????????Expression.Constant("打印出來") ????????????????);????????????//?調(diào)用屬性 ????????????MemberExpression?method2?=?Expression.Property(test,?"sample"); ????????????Expression?lambda1?=?Expression.Lambda(method1); ????????????lambda1.Compile()(); ????????????Expression>?lambda2?=?Expression.Lambda>(method2);????????????int?sample?=?lambda2.Compile()(); ????????????Console.WriteLine(sample); ????????????Console.ReadKey();

      四,實例化泛型類型于調(diào)用

      將 Test 類,改成這樣

      public?class?Test ????{ ????????public?void?Print(T?info) ????????{ ????????????Console.WriteLine(info); ????????} ????}

      Test 類已經(jīng)是一個泛型類,表達式實例化示例

      static?void?Main(string[]?args)????????{ ????????????RunExpression(); ????????????Console.ReadKey(); ????????}????????public?static?void?RunExpression() ????????{????????????//?調(diào)用構(gòu)造函數(shù) ????????????NewExpression?newA?=?Expression.New(typeof(Test));????????????//?實例化一個類型 ????????????MemberInitExpression?test?=?Expression.MemberInit(newA,????????????????new?List()?{?} ????????????????);????????????//?調(diào)用方法 ????????????MethodCallExpression?method?=?Expression.Call( ????????????????test,????????????????typeof(Test).GetMethod("Print").MakeGenericMethod(new?Type[]?{?typeof(T)?}), ????????????????Expression.Constant("打印出來") ????????????????); ????????????Expression?lambda1?=?Expression.Lambda(method); ????????????lambda1.Compile()(); ????????????Console.ReadKey(); ????????}

      五,定義集合變量、初始化、添加元素

      集合類型使用?ListInitExpression表示。

      創(chuàng)建集合類型,需要使用到

      ElementInit 表示 IEnumerable集合的單個元素的初始值設(shè)定項。

      ListInit 初始化一個集合。

      C# 中,集合都實現(xiàn)了 IEnumerable,集合都具有 Add 扥方法或?qū)傩浴?/p>

      使用 C# 初始化一個集合并且添加元素,可以這樣

      List?list?=?new?List() ????????????{????????????????"a",????????????????"b" ????????????};????????????list.Add("666");

      而在表達式樹里面,是通過 ElementInit 調(diào)用 Add 方法初始化/添加元素的。

      示例

      MethodInfo?listAdd?=?typeof(List).GetMethod("Add");????????????/* ?????????????*?new?List() ?????????????*?{ ?????????????*?????"a", ?????????????*?????"b" ?????????????*?}; ?????????????*/ ????????????ElementInit?add1?=?Expression.ElementInit( ????????????????listAdd, ????????????????Expression.Constant("a"), ????????????????Expression.Constant("b") ????????????????); ????????????//?Add("666") ????????????ElementInit?add2?=?Expression.ElementInit(listAdd,?Expression.Constant("666"));

      示例

      MethodInfo?listAdd?=?typeof(List).GetMethod("Add"); ????????????ElementInit?add1?=?Expression.ElementInit(listAdd,?Expression.Constant("a")); ????????????ElementInit?add2?=?Expression.ElementInit(listAdd,?Expression.Constant("b")); ????????????ElementInit?add3?=?Expression.ElementInit(listAdd,?Expression.Constant("666")); ????????????NewExpression?list?=?Expression.New(typeof(List));????????????//?初始化值 ????????????ListInitExpression?setList?=?Expression.ListInit(????????????????list, ????????????????add1, ????????????????add2, ????????????????add3 ????????????????);????????????//?沒啥執(zhí)行的,就這樣看看輸出的信息 ????????????Console.WriteLine(setList.ToString()); ????????????MemberExpression?member?=?Expression.Property(setList,?"Count"); ????????????Expression>?lambda?=?Expression.Lambda>(member);????????????int?result?=?lambda.Compile()(); ????????????Console.WriteLine(result); ????????????Console.ReadKey();

      一個逗逗的大學(xué)生

      軟件開發(fā)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:wpc excel怎么打開云文檔 - 一步步教你打開和編輯wpc excel云文檔的方法
      下一篇:Spring - 在ioc容器中裝配bean
      相關(guān)文章
      久久亚洲精品无码VA大香大香| 亚洲产国偷V产偷V自拍色戒 | 久久综合日韩亚洲精品色| 亚洲国产精品张柏芝在线观看| 久久久无码精品亚洲日韩软件| 亚洲一区在线观看视频| 亚洲AV无码乱码在线观看富二代 | 亚洲无人区午夜福利码高清完整版| 亚洲午夜福利在线视频| 久久av无码专区亚洲av桃花岛| 亚洲AV成人无码久久精品老人| 亚洲av鲁丝一区二区三区| 久久亚洲精品中文字幕无码| 亚洲高清国产AV拍精品青青草原| 亚洲A丁香五香天堂网 | 亚洲国产精品成人综合久久久| 亚洲免费在线视频观看| 亚洲AV无码国产精品色| 亚洲一区二区三区在线网站| 亚洲天堂中文字幕| 国产亚洲一区二区三区在线| 亚洲国产精品无码久久久不卡| 亚洲V无码一区二区三区四区观看| 亚洲AV无码一区二区三区DV| 亚洲第一精品福利| 亚洲精品无码Av人在线观看国产| 婷婷综合缴情亚洲狠狠尤物| 亚洲砖码砖专无区2023| 亚洲国产成人无码AV在线影院| 亚洲五月综合网色九月色| 亚洲一本一道一区二区三区| 亚洲国产精品成人午夜在线观看| 亚洲人成人网毛片在线播放| 亚洲成a人片在线观看播放| 亚洲丁香色婷婷综合欲色啪| 亚洲色图视频在线观看| 亚洲成人午夜在线| 亚洲国产精品午夜电影| 亚洲国产成人无码AV在线| 亚洲第一黄色网址| 亚洲精品制服丝袜四区|