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

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

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

      C#系列——記一次業(yè)務(wù)需求:對象的深拷貝

        這篇隨筆著實(shí)在意料之外,主要是源于上周開發(fā)BS的一個業(yè)務(wù),需要用到對象的深拷貝。說的直白一點(diǎn),就是將對象內(nèi)存分配區(qū)和引用完全拷貝一份新的。這種需求以前就遇到過,怎么解決的已經(jīng)記不清了。這次趁著這個機(jī)會將對象的深拷貝這個知識點(diǎn)記錄下。

        先來說說業(yè)務(wù)場景,直接上代碼:

             //0.反射得到工廠屬性
                  var lstRes = new List<List<DragElementProp>>();
                  var oType = typeof(Ewin.CommonLib.DtoModel.DTO_TM_PLANT);
                  var lstAttr = ReflectorAttribute(oType);
      
                  //1.給每個工廠對象的屬性賦值,構(gòu)造前臺需要的數(shù)據(jù)結(jié)構(gòu)
                  var lstPropModel = oType.GetProperties();
                  foreach (var oModel in lstModel)
                  {
                      var lstResTmp = new List<DragElementProp>();
                      foreach (var oAttr in lstAttr)
                      {
                          var oPropModel = lstPropModel.FirstOrDefault(x => x.Name == oAttr.Name);
                          if (oPropModel == null)
                          {
                              continue;
                          }
                          oAttr.Value = oPropModel.GetValue(oModel);
                  lstResTmp.Add(oAttr); }
      lstRes.Add(lstResTmp); }

      需求就是lstAttr變量保存的是一個List<DragElementProp>類型的集合,需要遍歷lstModel,需要將每一個的oModel的Name屬性的值賦給lstAttr實(shí)例的Value屬性。然后保存多個lstAttr的集合,形如List<List<DragElementProp>>。通過上面的代碼在foreach (var oModel in lstModel)里面每次new一個新的var lstResTmp = new List<DragElementProp>();來保存賦值后lstAttr,明眼人一看就知道這種方式肯定不行,因?yàn)镃#里面class是引用類型,每次改變的都是唯一的一個lstAttr實(shí)例,通過上面代碼的方式得到的lstRes肯定會是幾個相同的lstAttr,即最后一次賦值的lstAttr。

        怎么辦?各種百度、各種博客園。查了多篇博文,發(fā)現(xiàn)答案千篇一律,深拷貝對象的三種解決方案:

      • 實(shí)現(xiàn)ICloneable接口,自定義拷貝功能
      • 序列化/反序列化類實(shí)現(xiàn)
      • 通過反射實(shí)現(xiàn)

       

      我們逐一看看這幾種方式

      (1)實(shí)現(xiàn)ICloneable接口的方式,貼上園子里面的代碼

      public class Person:ICloneable 
      { 
          public int Age { get; set; } 
          public string Address { get; set; } 
          public Name Name { get; set; } 
          public object Clone() 
          { 
            Person tem = new Person(); 
            tem.Address = this.Address; 
            tem.Age = this.Age; 
            tem.Name = new Name(this.Name.FristName, this.Name.LastName); 
            return tem; 
          } 
      } 

      很顯然,這種方式不可取。如果一個類里面有多個其他類成員,那不是每個都要去定義這樣一個clone方法。太low。

       

      (2)序列化反序列化方式。貼上園子里面的代碼

      [Serializable] 
      public class Person : ICloneable 

        public
      object Clone()   {     using (MemoryStream ms = new MemoryStream(1000))     {       object CloneObject;       BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));       bf.Serialize(ms, this);       ms.Seek(0, SeekOrigin.Begin);       // 反序列化至另一個對象(即創(chuàng)建了一個原對象的深表副本)       CloneObject = bf.Deserialize(ms);       // 關(guān)閉流       ms.Close();       return CloneObject;     }   }
      }

      這種方式比上面方式好一點(diǎn),但是需要對象是可序列化的,即要加上[Serializable]特性標(biāo)簽,博主試過如果一個普通的類調(diào)用這個方法會報異常。

      博主用Newtonsoft.Json重新寫了個:

             foreach (var oModel in lstModel)
                  {
                      var lstResTmp = new List<DragElementProp>();
                      foreach (var oAttr in lstAttr)
                      {
                          var oPropModel = lstPropModel.FirstOrDefault(x => x.Name == oAttr.Name);
                          if (oPropModel == null)
                          {
                              continue;
                          }
                          oAttr.Value = oPropModel.GetValue(oModel);
                      }
                      //深拷貝一個集合到另一個集合
                      var oJsonValue = Newtonsoft.Json.JsonConvert.SerializeObject(lstAttr);
                      lstResTmp.AddRange(Newtonsoft.Json.JsonConvert.DeserializeObject<List<DragElementProp>>(oJsonValue));
                      lstRes.Add(lstResTmp);
                  }

      這種方式對對象沒什么太特殊的要求。

       

      (3)反射的方式,博主自己簡單寫了一個:

           public static T CloneModel<T>(T oModel)
              {
                  var oRes = default(T);
                  var oType = typeof(T);
      
                  //得到新的對象對象
                  oRes = (T)Activator.CreateInstance(oType);
      
                  //給新的對象復(fù)制
                  var lstPro = oType.GetProperties();
                  foreach (var oPro in lstPro)
                  {
                      //從舊對象里面取值
                      var oValue = oPro.GetValue(oModel);
      
                      //復(fù)制給新的對象
                      oPro.SetValue(oRes, oValue);
                  }
      
                  return oRes;
              }

      這種方式也比較簡單,但考慮到反射得性能問題,而且如果是clone集合,需要遍歷去反射這樣效率就更低。

       

        綜上所述:要深拷貝一個對象,其實(shí)上述無論哪種方式都是新產(chǎn)生一個對象,然后給新的對象依次賦值來實(shí)現(xiàn)。方案一一般不可取,方案二在集合的序列化方便可能效率稍微高點(diǎn),方案三如果只是簡單的拷貝一個對象我覺得也是不錯的選擇。反正博主更加偏好方案二,用起來簡單。

        

        反正找了好久說的都這三種方式,這次先記錄下,如果沒有更好的方式就用這些方案先解決吧,當(dāng)然,如果以后知道了更好的方式也可以拿出來和大家分享。也不知道.Net是否預(yù)留了某些特殊的通道來處理這種深拷貝。希望知道的大俠多多指教~~

       

      posted @ 2015-07-28 15:10  懶得安分  閱讀(8509)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 亚洲大尺度一区二区av| 在线观看精品日本一区二| 麻豆蜜桃伦理一区二区三区| 无码人妻丝袜在线视频| 久久精品亚洲精品国产色婷 | 亚洲gv天堂无码男同在线观看| 99久久精品国产熟女拳交| 最新国产精品拍自在线播放| 亚洲精品二区在线播放| 久久精品国产熟女亚洲av| 亚洲av午夜成人片| 69精品丰满人妻无码视频a片 | 久久久久人妻精品一区三寸 | 欧美自拍嘿咻内射在线观看| 成人爽a毛片免费| 99久久er热在这里只有精品99| 成人午夜视频一区二区无码| 国产成人综合色视频精品| 高清无打码一区二区三区| 日韩国产中文字幕精品| 国产69精品久久久久人妻刘玥| 美女人妻激情乱人伦 | 92精品国产自产在线观看481页| 奇米777四色影视在线看| 成人区人妻精品一区二蜜臀| 精品国产成人国产在线视| 亚洲永久一区二区三区在线| 五月综合网亚洲乱妇久久| 国产av综合色高清自拍| 国产高清在线精品一区| 办公室强奷漂亮少妇视频 | 国产91午夜福利精品| 国产-第1页-浮力影院| 99久久精品看国产一区| 无套内谢极品少妇视频| 国产精品无码久久久久AV| 亚洲精品无码高潮喷水A| 国产极品粉嫩学生一线天| 97人妻免费碰视频碰免| 国产精品污双胞胎在线观看| 国产精品国产亚洲看不卡|