<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      c#表達式樹入門,看這個就夠了

      題記:
      由于反射需要大量的性能開銷,所以推薦用表達式樹或者emit,但是emit 如果不熟悉指令編程的話,使用成本很大,所以優先推薦表達式樹,但是網上給出來的文檔 都非常的復雜,只是帶你使用,剛好我團隊的小伙伴也不太理解,所以我來整理一篇簡單入門版本的.
      問: 反射有3種方式,一個是獲取值,一個是賦值,一個是調用方法 (如構造器 靜態方法 普通方法等),哪個才是性能元兇
      先總結: 表達式樹 就是代碼的拼接, 所以有以下三個區域
      - 入參
      - 代碼塊
      - 返回值
      1. 入參:
        Expression.Parameter()
      2. 代碼塊
      • 常見的代碼塊 加/減/乘/除/等于/獲取字段值/獲取屬性值/調用方法/new對象
      • Expression.Property()獲取某對象字段的值  test.M
      • Expression.Assign(), 給對象屬性或字段賦值 test.M = ""
      • Expression.Multiply(),加減乘除 的方法
      • Expression.Call(), 調用某對象的方法,可以是靜態
      • Expression.Constant() 常值 比如  1  其實應該是 Constant("This is t2 name", typeof(String));
      • Expression.New()創建對象
      • Expression.NotEqual ELSE For循環等等,這個入門后 自己查資料即可
      • Expression.Convert(),強制性轉換 如 Expression.Convert()配合Call

        3. 出參 或者 返回值

      • 返回值 其實就是2個:
      • 無返回 值即 可執行的代碼塊{}, 
      • 返回一個值 如 new對象,入參的對象,常量值,或者 List數組
      • Expression.Block()
      • Expression.MemberInit()
      • Expression.ListInit()
        其實理論上來說,表達式樹沒有固定的返回的值,因為 表達式樹中不允許出現return,只是調用Compile()的推測,所以其實 返回值 只有一個Block**,其他全部是 代碼塊,只不過我覺得這時候應該區分出來,這個也是所有的表達式樹在調用Lamda 的時候標準寫法都是 Block包裝,可以省略。
      以下是例子的由簡單到復雜的匯總,代碼在后面的框里面
      1. Expression<Func<int, int, int>> func = (m, n) => m \* n;
      2. Expression<Func<T01, String>> func = (T01 m) => m.Name;
      3. Expression<Action<T01,String>> func = (T01 m, String str) => m.Name = str;
      4. Expression<Func<String, T01>> expression1 = (String str)=>new T01() { Name = str };
      5. Expression<Action<T01,T02>> action = (T01 t1, T02 t2)=> t2.Name = t1.Name;
      6. Fun<T01, T02> func = T01 t1 => new T02(){ Name = t1.Name}
      //1.Expression<Func<int, int, int>> func = (m, n) => m \* n;
      //入參
      ParameterExpression t1 = Expression.Parameter(typeof(Int32), "t1");
      ParameterExpression t2 = Expression.Parameter(typeof(Int32), "t2");
      //代碼塊
      BinaryExpression multiply = Expression.Multiply(t1, t2);
      //返回值Block
      BlockExpression block = Expression.Block(multiply);
      //編譯
      Expression<Func<int, int, int>> expression =  Expression.Lambda<Func<int, int, int>>(block, t1, t2);
      Func<int, int, int> func = expression.Compile();
      

        

      //上面說了 表達式樹不允許出現顯示的代碼塊 不允許出現return,所以注意以下錯誤的寫法
      
      ```c#
      Expression<Func<int, int,int>> expression = (m,n)=> m * n;
      //以下是錯誤形式
      Expression<Action<int, int>> expression = (m,n)=> { };
      Expression<Action<int, int>> expression = (m,n)=> {m + n };
      Expression<Func<int, int,int>> expression = (m,n)=> { return m + n; };
      

        

      public class T01
      {
          public String Name { get; set; }
      }
      
      public class T02
      {
          public String Name { get; set; }
      }
      

        

      //操作 Expression<Func<T01, String>> func = (T01 m) => m.Name;
      
      //入參
      ParameterExpression m = Expression.Parameter(typeof(T01), "m");
      //代碼塊
      MemberExpression left = Expression.Property(m, typeof(T01).GetProperty(nameof(T01.Name)));
      //錯誤的寫法是 
      //Expression.Property(null, typeof(T01).GetProperty(nameof(T01.Name))),
      //因為有些以為 我都 傳了typeof(Test) 肯定獲取到對應屬性的值,
      //其實表達式樹是 編譯代碼的,所以每一步都得實現,少一個不可。
      //這里的 是 m.Name 其實分為3步  m  .   Name,都必須有
      
      //返回值
      BlockExpression block1 = Expression.Block(left);
      Expression<Func<T01, String>> expression = Expression.Lambda<Func<T01, String>>(block1, m);
      Func<T01, String> func = expression.Compile();
      

        

       //Expression<Action<T01>> func = (T01 m) => m.Name = "new name";
      
      //入參
      ParameterExpression m = Expression.Parameter(typeof(T01), "m");
      //代碼塊
      //拼接 m.Name
      MemberExpression left = Expression.Property(m, typeof(T01).GetProperty(nameof(T01.Name)));
      // m.Name = "new name"
      BinaryExpression assignExpression1 = Expression.Assign(left, Expression.Constant("new name", typeof(String)));
      //返回值 此處無
      BlockExpression block = Expression.Block(assignExpression1);
      Expression<Action<T01>> expression = Expression.Lambda<Action<T01>>(block, m);
      Action<T01> func = expression.Compile();
      T01 t01 = new T01() { Name = "old name" };
      func(t01);
      Console.WriteLine(t01.Name);//new name
      

        

      // Expression<Action<T01,String>> func = (T01 m, String str) => m.Name = str;
      
      //入參
      ParameterExpression m = Expression.Parameter(typeof(T01), "m");
      ParameterExpression str = Expression.Parameter(typeof(String), "str");
      //代碼塊
      //拼接 m.Name
      MemberExpression left = Expression.Property(m, typeof(T01).GetProperty(nameof(T01.Name)));
      // m.Name = str
      //Assign 賦值的
      BinaryExpression assignExpression1 = Expression.Assign(left, left);
      //返回值
      BlockExpression block = Expression.Block(assignExpression1);
      Expression<Action<T01, String>> expression = Expression.Lambda<Action<T01, String>>(block, m, str);
      Action<T01, String> func = expression.Compile();
      T01 t01 = new T01() { Name = "old name" };
      func(t01,"new name");
      Console.WriteLine(t01.Name);//new name
      

        

      //Expression<Func<String, T01>> expression1 = (String str)=>new T01() { Name = str };
      //入參
      ParameterExpression str = Expression.Parameter(typeof(String), "str");
      //代碼塊
      MemberAssignment bind = Expression.Bind(typeof(T01).GetProperty(nameof(T01.Name)), str);
      //返回值
      MemberInitExpression newT01 = Expression.MemberInit(Expression.New(typeof(T01)), bind);
      BlockExpression block = Expression.Block(newT01);
      Expression<Func<String, T01>> expression = Expression.Lambda<Func<String, T01>>(block,str);
      Func<String, T01> func = expression.Compile();
      T01 t01 = new T01() { Name = "old name" };
      t01 = func("new name");
      Console.WriteLine(t01.Name);//new name
      

        

      這里有個問題是  new T01(){}; 
        4.1. 這里是對象初始化模塊,而不是 var t01 = new T02();t02.Name="";
      所以一定得區分,**而對象初始化模塊 用得 Bind() 關系處理的,需要和Assign()區分開來
        4.2. 注意Expression.MemberInit(Expression.New(typeof(T01))) == Expression.New(typeof(T01)), 如果沒有綁定關系 其實可以去掉 MemberInit()的寫法,就和 可以去掉所有的Block一樣,以及 Expression.Property()只傳遞一個 name 值一樣,其實里面做了簡化
      Expression<Action<T01,T02>> action = (T01 t1, T02 t2)=> t2.Name = t1.Name;
      
      //入參
      ParameterExpression t1 = Expression.Parameter(typeof(T01), "t1");
      ParameterExpression t2 = Expression.Parameter(typeof(T02), "t2");
      //代碼塊
      //第二步,t2.Name 拆解為 參數t2, 屬性符號 . 屬性名稱 Name
      var member1 = Expression.Property(t2, nameof(T02.Name));
      //拆解 t1.Name
      var member2 = Expression.Property(t1, nameof(T01.Name));
      //將member2賦值給member1
      var member = Expression.Assign(member1, member2);
      
      Expression block = Expression.Block(member);
      Expression<Action<T01, T02>> expression = Expression.Lambda<Action<T01, T02>>(block, t1, t2);
      var func = expression.Compile();
      T01 t01 = new T01() { Name = "This is t1 name" };
      T02 t02 = new T02() { Name = "This is t2 name" };
      
      func(t01, t02);
      Console.WriteLine(t02.Name); //輸出的是 This is t1 name; 
      

        

      Fun<T01, T02> func = T01 t1 => new T02(){ Name = t1.Name}的轉換器
      
      //定義入參
      ParameterExpression t1 = Expression.Parameter(typeof(T01), "t1");
      //代碼塊
      //拆解 t1.Name
      var member2 = Expression.Property(t1, nameof(T01.Name));
      //因為這里是new,所以 這里實際是 綁定 T02.Name與 T01.Name的關系
      var member = Expression.Bind(typeof(T02).GetProperty(nameof(T02.Name)), member2);
      //當創建對象的時候,依據綁定關系 new T02()
      //當然也可以 var member = Expression.Bind(typeof(T02).GetProperty(nameof(T02.Name)), Expression.Constant("xxxxx"));
      //如果沒有 member 那么可以直接 New() 不需要MemberInit()
      Expression block = Expression.Block(Expression.MemberInit(Expression.New(typeof(T02)), member));
      Expression<Func<T01, T02>> expression = Expression.Lambda<Func<T01, T02>>(block, t1);
      var func = expression.Compile();
      T01 t01 = new T01() { Name = "This is t1 name" };
      T02 t02 = new T02() { Name = "This is t2 name" };
      
      t02 = func(t01);
      Console.WriteLine(t02.Name);//這里輸出的  "This is t1 name"
      

        

      **注意 這里是 Bind() 而不是 Assign(), 那這里可以用 Assign()嗎?**

       答案是不行.因為 Assign 的寫法就是  T02 t02 = new T02(); t02.Name = t01.Name;return t02; 這個原因上面解釋過, 這里在強調下, 表達式樹 不允許代碼塊,不允許return,只允許單操作.

      最后 在強調下,表達式樹 其實 就是 入參 出參 返回的代碼拼接,然后執行成 我們想要的代碼,雖然看起來復雜,但是實際就是一步步來的.
       

      留個作業,

      1. 將上面的 Fun<T01, T02> func 改成通用的寫法. 下面直接貼了,我在本地沒調試,大家可以自己調試下
      2. 如何實現 Expression.Call 的執行方式 
      3. 將注釋上面的功能都實現一遍
      public class MapHelper
      {
          private static Dictionary<String, Object> dicFunc = new Dictionary<string, Object>();
                  /// 沒有判斷泛型 IsGenericType
              /// 沒操作 屬性 不同類型 轉不同類型的操作(重新調用Map類即可), ps => IEnumerable 轉換需要調用 Expression.Call( IEnumerable.Select(Map) )來處理轉換條件
              /// 沒操作 IsNullable 轉為值類型數據轉換  需要 Expression.PropertyType("value")來強制性賦值到 基礎類型
              /// 沒操作 特性轉換
              /// 可以理解成只做 類型相同字段 的  值賦值轉換
          public static void Map<T1, T2>(T1 source, T2 destination) where T1 : class, new() where T2 : class, new()
          {
              Type tIn = typeof(T1);
              Type tResult = typeof(T2);
              String key = $"{tIn}_Convert_{tResult}";
              if (!dicFunc.TryGetValue(key, out var func))
              {
                  lock (dicFunc)
                  {
                      if (!dicFunc.TryGetValue(key, out func))
                      {
                          ParameterExpression t1 = Expression.Parameter(tIn);
                          ParameterExpression t2 = Expression.Parameter(tResult);
                          List<Expression> list = new List<Expression>();
                          Dictionary<PropertyInfo, PropertyInfo> map = new Dictionary<PropertyInfo, PropertyInfo>();
                          foreach (var item in tResult.GetProperties().Where(x => x.PropertyType.IsPublic && x.CanWrite && x.CanRead))
                          {
                              String name = item.Name;
                              var p1 = tIn.GetProperty(name);
                              if (p1 == null) continue;
                              if (!p1.PropertyType.IsPublic || !p1.CanWrite || !p1.CanRead || p1.PropertyType != item.PropertyType) continue;
                              MemberExpression mIn = Expression.Property(t1, p1);
                              MemberExpression mResult = Expression.Property(t2, item);
                              var memberBinding = Expression.Assign(mResult, mIn);
                              list.Add(memberBinding);
                          }
                          Expression<Action<T1, T2>> lambda = Expression.Lambda<Action<T1, T2>>(Expression.Block(list), t1, t2);
                          var action = lambda.Compile();
                          dicFunc[key] = action;
                          func = action;
                      }
                  }
              }
              ((Action<T1, T2>)func)(source, destination);
          }
          public static TResult Map<TIn, TResult>(TIn source) where TIn : class, new() where TResult : class, new()
          {
              Type tIn = typeof(TIn);
              Type tResult = typeof(TResult);
              String key = $"{tIn}_New_{tResult}";
              if (!dicFunc.TryGetValue(key, out var func))
              {
                  lock (dicFunc)
                  {
                      if (!dicFunc.TryGetValue(key, out func))
                      {
                          ParameterExpression t1 = Expression.Parameter(tIn);
      
                          List<MemberBinding> list = new List<MemberBinding>();
                          foreach (var item in tResult.GetProperties().Where(x => x.PropertyType.IsPublic && x.CanWrite && x.CanRead))
                          {
                              String name = item.Name;
                              var p1 = tIn.GetProperty(name);
                              if (p1 == null) continue;
                              if (!p1.PropertyType.IsPublic || !p1.CanWrite || !p1.CanRead || p1.PropertyType != item.PropertyType) continue;
                              MemberExpression property1 = Expression.Property(t1, p1);
                              var memberBinding = Expression.Bind(item, property1);
                              list.Add(memberBinding);
                          }
                          Expression<Func<TIn, TResult>> lambda;
                          if (list.Count == 0)
                          {
                              lambda = Expression.Lambda<Func<TIn, TResult>>(Expression.Block(Expression.Constant(null, tResult)), t1);
                          }
                          else
                          {
                              lambda = Expression.Lambda<Func<TIn, TResult>>(Expression.MemberInit(Expression.New(tResult), list), t1);
                          }
                          var action = lambda.Compile();
                          dicFunc[key] = action;
                          func = action;
                      }
                  }
              }
              return ((Func<TIn, TResult>)func)(source);
          }
      }
      View Code

       

      posted @ 2024-11-01 13:37  Best_Hong  閱讀(165)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精欧美一区二区三区| 美女黄18以下禁止观看| 亚洲丰满熟女一区二区蜜桃| 最新亚洲av日韩av二区| 丝袜老师办公室里做好紧好爽| 3d无码纯肉动漫在线观看| 国产偷国产偷亚洲高清人| 久久人人97超碰精品| 国产精品无遮挡又爽又黄| 国产高清在线男人的天堂| 欧美黑人粗暴多交高潮水最多 | 国产中文三级全黄| 91精品亚洲一区二区三区| 国产一区二区三区黄色片| 国产一区日韩二区欧美三区| 国产精品久久久久影院| 国内精品视频区在线2021| 欧美久久精品一级c片免费| 青青草无码免费一二三区| 日韩精品一二三黄色一级| 青青草无码免费一二三区| 日韩人妻无码一区二区三区| 久久中文字幕无码专区| 国内精品久久久久影院不卡| 国产精品国产三级国产试看 | 国产精品人妻久久ai换脸| 99久久国产综合精品成人影院| av天堂久久精品影音先锋| 永平县| 久久精品国产精品第一区| 十八禁午夜福利免费网站| 久久69国产精品久久69软件| 美日韩精品一区二区三区| 国产精品国产三级国产试看| 国产无套内射又大又猛又粗又爽| 晋州市| 99久久99这里只有免费费精品 | 亚洲电影天堂在线国语对白| 在线观看中文字幕国产码| 日韩人妻一区中文字幕| 日韩在线视频一区二区三|