一、前言
开发过程中经常会遇到某个引用类型对象类的拷贝,拿到一个新的备份实列进行修改,而不影响原有的对象实例,通常有浅拷贝和深拷贝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 中使用深度拷贝提示过时,一脸懵逼,网上搜索了半天才找到相关资料,有用的话记得收个藏,点个赞。