【.Net Core】【4】浅拷贝、深度拷贝

文章目录


一、前言

开发过程中经常会遇到某个引用类型对象类的拷贝,拿到一个新的备份实列进行修改,而不影响原有的对象实例,通常有浅拷贝和深拷贝2种。

二、序列化标记

将对需要拷贝的对象类标记为可序列化 [Serializable] ,测试过程发现貌似不加也没有问题。

 [Serializable] //标记为可序列化 测试过程发现貌似不加也没有问题
 public class DeviceLocation : ICloneable
    {
        public Device Device { get; set; }       
        public int Age { get; set; }
    }      
   
 public class Device
   {
 		public string {get;set;}
   }  

三、浅拷贝复制

拷贝前后的Object1 Object2,两个对象中的值类型Age互不影响,但是对象中的引用类型Device依然指向同一个地址,改变其中1个Object的 Device 属性 另一个Object对象中的Device也会同步更改。

浅拷贝个人通常用在.netcore EntityFrameworkCore数据库查询的时候使用,从数据库查询出来的某条记录Entity带有数据库标记状态绑定,直接更改这个Entity后可能会自动保存回数据库表中,显然这不是我们期望的,这时候可以采用浅拷贝的方式,获取这条记录自行修改使用。【领域层直接查询某条记录实体未进行 Dto转换时】

 public class DeviceLocation : ICloneable
    {
        public Device Device { get; set; }       
        public int Age { get; set; }
    }   

   /// <summary>
   /// 浅拷贝:用于从数据库查询引用拷贝
   /// </summary>
   /// <returns></returns>
   public object Clone()
   {
       return this.MemberwiseClone();
   }

   /// <summary>
   /// 浅拷贝:用于从数据库查询引用拷贝
   /// </summary>
   /// <returns></returns>
   public DeviceLocation ShallowClone()
   {
       return this.Clone() as DeviceLocation;
   }

四、深度拷贝复制:.net 5版本以前

完全复制一个权限的互不牵扯的对象,不管对象中是否有嵌套对象。

 [Serializable]
 public class DeviceLocation
    {
        public Device Device { get; set; }       
        public int Age { get; set; }

	    /// <summary>
	    /// 深度拷贝: 针对.net 5版本以前,新版本过时提示
    	/// </summary>
	    /// <returns></returns>
    	public DeviceLocation DeepClone()
	    {
    	    using (System.IO.Stream os = new System.IO.MemoryStream())
        	{
            	System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
	            formatter.Serialize(os, this);
    	        os.Seek(0, System.IO.SeekOrigin.Begin);
        	    return formatter.Deserialize(os) as DeviceLocation;
	        }
    	}
    }   

五、深度拷贝复制:.net 5 以后 .net core

完全复制一个权限的互不牵扯的对象,不管对象中是否有嵌套对象。

 [Serializable]
 public class DeviceLocation
    {
        public Device Device { get; set; }       
        public int Age { get; set; }

	    /// <summary>
	    /// 深度拷贝:嵌套对象也完全独立
	    /// </summary>
	    /// <returns></returns>
	    public ICruiseHelper DeepClone()
	    {
     	   var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
	       var serializeSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
    	   return JsonConvert.DeserializeObject<DeviceLocation>(JsonConvert.SerializeObject(this, serializeSettings), deserializeSettings);
	    }

    }   

六、深度拷贝复制:独立封装

    /// <summary>
	/// 深度克隆辅助类
	/// </summary>
	public static class CloneHelper
	{
		/// <summary>
		/// 深度克隆
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="source"></param>
		/// <returns></returns>
		public static T DeepClone<T>(this T source)
		{
			// Don't serialize a null object, simply return the default for that object
			if (Object.ReferenceEquals(source, null))
			{
				return default(T);
			}

			var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
			var serializeSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
			return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, serializeSettings), deserializeSettings);
		}
	}

七、总结

这两天在.netcore 中使用深度拷贝提示过时,一脸懵逼,网上搜索了半天才找到相关资料,有用的话记得收个藏,点个赞。

上一篇:几款Android 应用自动化测试工具


下一篇:kubernetes 设备插件