首页 > 其他分享 >.NET 实现实体对象深拷贝(克隆/复制)的几种方法

.NET 实现实体对象深拷贝(克隆/复制)的几种方法

时间:2022-12-10 21:56:06浏览次数:47  
标签:克隆 对象 Dog public new NET 拷贝 Name

一、浅拷贝:指对象的字段被拷贝,而字段引用的对象不会被拷贝,拷贝对象和原对象仅仅是引用名称有所不同,但是它们共用一份实体。对任何一个对象的改变,都会影响到另外一个对象。大部分的引用类型,实现的都是浅拷贝,引用类型对象之间的赋值,就是复制一个对象引用地址的副本,而指向的对象实例仍然是同一个。

  • 给字段挨个赋值(缺点是没有扩展性)
  • .NET里面也提供了一个方法MemberwiseClone,这个方法默认就是返回当前对象的副本,所以浅拷贝可以这样实现:
  public People ShallowCopy()
  {
     return (People)this.MemberwiseClone();
  }

前台调用如下:

public class Employee
{
    public string Name { get; set; }

    public Dog Dog { get; set; }  // 新增复杂对象

    public Employee Copy() => this.MemberwiseClone() as Employee;
}

public class Dog
{
    public string Name { get; set; }
}

Dog dog = new Dog() { Name = "小狗钱钱" };
Employee e1 = new Employee() { Name = "张三", Dog = dog };
Employee e2 = e1.Copy();

e2.Name = "李四";
Console.WriteLine(e1.Name);                             // 张三
Console.WriteLine(e2.Name);                             // 李四
Console.WriteLine(ReferenceEquals(e1, e2));             // False

// 新增比较
e1.Dog.Name = "小狗";
Console.WriteLine(e1.Dog.Name);                         // 小狗
Console.WriteLine(e2.Dog.Name);                         // 小狗
Console.WriteLine(ReferenceEquals(e1.Dog, e2.Dog));     // True

 

 

二、深拷贝:指对象的子段被拷贝,同时字段引用的对象也进行了拷贝。深拷贝创建的是整个源对象的结构,拷贝对象和原对象相互独立,不共享任何实例数据,修改一个对象不会影响到另一个对象。值类型之间的赋值操作,执行的就是深拷贝。


方式一: 使用二进制流

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
 
/// <summary>
/// 参考 http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// </summary>
public static class ObjectCopier
{
    public static T Clone<T>(T source)
    {
        if (!typeof(T).IsSerializable)
        {
            throw new ArgumentException("The type must be serializable.", "source");
        }
 
        if (Object.ReferenceEquals(source, null))
        {
            return default(T);
        }
 
        IFormatter formatter = new BinaryFormatter();
        Stream stream = new MemoryStream();
        using (stream)
        {
            formatter.Serialize(stream, source);
            stream.Seek(0, SeekOrigin.Begin);
            return (T)formatter.Deserialize(stream);
        }
    }
}

方式二 使用序列化与反序列化

public static T CloneJson<T>(this T source)
{            
    if (Object.ReferenceEquals(source, null))
    {
        return default(T);
    }
 
    var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};
    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}

方式三 使用反射

public static T DeepCopyByReflect<T>(T obj)
{
    //如果是字符串或值类型则直接返回
    if (obj is string || obj.GetType().IsValueType) return obj;
    object retval = Activator.CreateInstance(obj.GetType());
    FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
    foreach (FieldInfo field in fields)
    {
        try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }
        catch { }
    }
    return (T)retval;
}

方式四 使用XML序列化与反序列化

public static T DeserializeXML<T>(string xmlData) where T:new()
    {
        if (string.IsNullOrEmpty(xmlData))
            return default(T);
 
        TextReader tr = new StringReader(xmlData);
        T DocItms = new T();
        XmlSerializer xms = new XmlSerializer(DocItms.GetType());
        DocItms = (T)xms.Deserialize(tr);
 
        return DocItms == null ? default(T) : DocItms;
    }

 

标签:克隆,对象,Dog,public,new,NET,拷贝,Name
From: https://www.cnblogs.com/gougou1981/p/16972419.html

相关文章