<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      目錄

      * 表達(dá)式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)
      <https://www.cnblogs.com/whuanle/p/11569083.html#表達(dá)式樹練習(xí)實踐c值類型引用類型泛型集合調(diào)用函數(shù)>
      * 一,定義變量 <https://www.cnblogs.com/whuanle/p/11569083.html#一定義變量>
      * 二,訪問變量/類型的屬性字段和方法
      <https://www.cnblogs.com/whuanle/p/11569083.html#二訪問變量類型的屬性字段和方法>
      * 1. 訪問屬性 <https://www.cnblogs.com/whuanle/p/11569083.html#訪問屬性>
      * 2. 調(diào)用函數(shù) <https://www.cnblogs.com/whuanle/p/11569083.html#調(diào)用函數(shù)>
      * 三,實例化引用類型 <https://www.cnblogs.com/whuanle/p/11569083.html#三實例化引用類型>
      * 四,實例化泛型類型于調(diào)用 <https://www.cnblogs.com/whuanle/p/11569083.html#四實例化泛型類型于調(diào)用>
      * 五,定義集合變量、初始化、添加元素
      <https://www.cnblogs.com/whuanle/p/11569083.html#五定義集合變量初始化添加元素>
      表達(dá)式樹練習(xí)實踐:C#值類型、引用類型、泛型、集合、調(diào)用函數(shù)



      一,定義變量

      C# 表達(dá)式樹中,定義一個變量,使用 ParameterExpression。

      創(chuàng)建變量結(jié)點的方法有兩種,
      Expression.Parameter() Expression.Variable() // 另外,定義一個常量可以使用
      Expression.Constant()。
      兩種方式都是生成 ParameterExpression 類型 Parameter() 和 Variable() 都具有兩個重載。他們創(chuàng)建一個
      ParameterExpression節(jié)點,該節(jié)點可用于標(biāo)識表達(dá)式樹中的參數(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 不允許。

      筆者在官方文檔和其他作者文章上,都沒有找到具體區(qū)別是啥,去 stackoverflow 搜索和查看源代碼后,確定他們的區(qū)別在于 Variable 不能使用
      ref 類型。

      從字面意思來看,聲明一個變量,應(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ū)嵗囊妙愋?,是變量?br>
      類型,就是指引用類型,不需要實例化的靜態(tài)類型或者靜態(tài)屬性字段/方法。

      上面的解釋不太嚴(yán)謹(jǐn),下面示例會慢慢解釋。

      1. 訪問屬性

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

      調(diào)用靜態(tài)類型屬性

      Console 是一個靜態(tài)類型,Console.Title 可以獲取編譯器程序的實際位置。
      Console.WriteLine(Console.Title);
      使用表達(dá)式樹表達(dá)如下
      MemberExpression member = Expression.Property(null,
      typeof(Console).GetProperty("Title")); Expression<Func<string>> lambda =
      Expression.Lambda<Func<string>>(member); string result = lambda.Compile()();
      Console.WriteLine(result); Console.ReadKey();
      因為調(diào)用的是靜態(tài)類型的屬性,所以第一個參數(shù)為空。

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

      調(diào)用實例屬性/字段

      C#代碼如下
      List<int> a = new List<int>() { 1, 2, 3 }; int result = a.Count;
      Console.WriteLine(result); Console.ReadKey();
      在表達(dá)式樹,調(diào)用實例的屬性
      ParameterExpression a = Expression.Parameter(typeof(List<int>), "a");
      MemberExpression member = Expression.Property(a, "Count");
      Expression<Func<List<int>, int>> lambda = Expression.Lambda<Func<List<int>,
      int>>(member, a); int result = lambda.Compile()(new List<int> { 1, 2, 3 });
      Console.WriteLine(result); Console.ReadKey();
      除了 Expression.Property() ,其他的方式請自行測試,這里不再贅述。

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

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

      調(diào)用靜態(tài)類型的函數(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<Action>
      lambda = Expression.Lambda<Action>(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ù)。

      調(diào)用實例的函數(shù)

      寫一個類
      public class Test { public void Print(string info) { Console.WriteLine(info);
      } }
      調(diào)用實例的 Printf() 方法
      Test test = new Test(); test.Print("打印出來"); Console.ReadKey();
      表達(dá)式表達(dá)如下
      ParameterExpression a = Expression.Variable(typeof(Test), "test");
      MethodCallExpression method = Expression.Call( a,
      typeof(Test).GetMethod("Print", new Type[] { typeof(string) }),
      Expression.Constant("打印出來") ); Expression<Action<Test>> lambda =
      Expression.Lambda<Action<Test>>(method,a); lambda.Compile()(new Test());
      Console.ReadKey();
      注意的是,Expression.Variable(typeof(Test), "test");
      僅定義了一個變量,還沒有初始化/賦值。對于引用類型來說,需要實例化。

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

      三,實例化引用類型

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

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

      new

      使用 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));
      默認(rèn)沒有參數(shù)的構(gòu)造函數(shù),或者只有一個構(gòu)造函數(shù),像上面這樣調(diào)用。

      如果像指定一個構(gòu)造函數(shù),可以
      NewExpression newA = Expression.New(typeof(Test).GetConstructor(xxxxxx));
      這里就不詳細(xì)說了。

      給屬性賦值

      實例化一個構(gòu)造函數(shù)的同時,可以給屬性賦值。
      public static MemberInitExpression MemberInit(NewExpression newExpression,
      IEnumerable<MemberBinding> 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) );
      創(chuàng)建引用類型
      Expression.MemberInit()
      表示調(diào)用構(gòu)造函數(shù)并初始化新對象的一個或多個成員。

      如果實例化一個類,可以使用
      NewExpression newA = Expression.New(typeof(Test)); MemberInitExpression test
      = Expression.MemberInit(newA, new List<MemberBinding>() { } );
      如果要在實例化時給成員賦值
      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<MemberBinding>() { 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<MemberBinding>() { 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<Action> lambda1 =
      Expression.Lambda<Action>(method1); lambda1.Compile()(); Expression<Func<int>>
      lambda2 = Expression.Lambda<Func<int>>(method2); int sample =
      lambda2.Compile()(); Console.WriteLine(sample); Console.ReadKey();
      四,實例化泛型類型于調(diào)用

      將 Test 類,改成這樣
      public class Test<T> { public void Print<T>(T info) {
      Console.WriteLine(info); } }
      Test 類已經(jīng)是一個泛型類,表達(dá)式實例化示例
      static void Main(string[] args) { RunExpression<string>(); Console.ReadKey();
      } public static void RunExpression<T>() { // 調(diào)用構(gòu)造函數(shù) NewExpression newA =
      Expression.New(typeof(Test<T>)); // 實例化一個類型 MemberInitExpression test =
      Expression.MemberInit(newA, new List<MemberBinding>() { } ); // 調(diào)用方法
      MethodCallExpression method = Expression.Call( test,
      typeof(Test<T>).GetMethod("Print").MakeGenericMethod(new Type[] { typeof(T) }),
      Expression.Constant("打印出來") ); Expression<Action> lambda1 =
      Expression.Lambda<Action>(method); lambda1.Compile()(); Console.ReadKey(); }
      五,定義集合變量、初始化、添加元素

      集合類型使用 ListInitExpression表示。

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

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

      ListInit 初始化一個集合。

      C# 中,集合都實現(xiàn)了 IEnumerable,集合都具有 Add 扥方法或?qū)傩浴?br>
      使用 C# 初始化一個集合并且添加元素,可以這樣
      List<string> list = new List<string>() { "a", "b" }; list.Add("666");
      而在表達(dá)式樹里面,是通過 ElementInit 調(diào)用 Add 方法初始化/添加元素的。

      示例
      MethodInfo listAdd = typeof(List<string>).GetMethod("Add"); /* * new
      List<string>() * { * "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<string>).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<string>)); // 初始化值 ListInitExpression setList =
      Expression.ListInit( list, add1, add2, add3 ); // 沒啥執(zhí)行的,就這樣看看輸出的信息
      Console.WriteLine(setList.ToString()); MemberExpression member =
      Expression.Property(setList, "Count"); Expression<Func<int>> lambda =
      Expression.Lambda<Func<int>>(member); int result = lambda.Compile()();
      Console.WriteLine(result); Console.ReadKey();

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          黄蓉洗澡被老汉玩出精视频 | 一二三区欧美日韩人妻在线 | 97精品资源 | 国产美女色黄A片视频老师 | 小舞被各种性器折磨哭求饶的视频 | 亚洲三级片在线视频 | 色综合色婷婷 | 国产精品淫片 | ass东方少妇pics | 国产又大又粗又猛又爽的视频 |