C#对象的深层副本

我正在研究一些用C#编写的代码。 在这个应用程序中,我有一个自定义集合定义如下:

public class ResultList : IEnumerable { public List Results { get; set; } public decimal CenterLatitude { get; set; } public decimal CenterLongitude { get; set; } } 

Results使用的类型是三种自定义类型之一。 每个自定义类型的属性只是基本类型(整数,字符串,bools,int?,bool?)。 以下是其中一种自定义类型的示例:

 public class ResultItem { public int ID { get; set; } public string Name { get; set; } public bool? isLegit { get; set; } } 

如何执行我创建的ResultList对象的深层副本。 我发现这篇文章: 创建集合中所有元素的深层副本的通用方法 。 但是,我无法弄清楚如何做到这一点。

您的ResultList类无法使用Jon Skeet的示例的原因之一是因为它没有实现ICloneable接口。

在您需要克隆的所有类上实现ICloneable,例如

 public class ResultItem : ICloneable { public object Clone() { var item = new ResultItem { ID = ID, Name = Name, isLegit = isLegit }; return item; } } 

还有ResultList:

 public class ResultList : IEnumerable, ICloneable where T : ICloneable { public List Results { get; set; } public decimal CenterLatitude { get; set; } public decimal CenterLongitude { get; set; } public object Clone() { var list = new ResultList { CenterLatitude = CenterLatitude, CenterLongitude = CenterLongitude, Results = Results.Select(x => x.Clone()).Cast().ToList() }; return list; } } 

然后制作对象的深层副本:

 resultList.clone(); 

涉及编码最少的方法是通过BinaryFormatter进行序列化和反序列化。

您可以定义以下扩展方法(取自Kilhoffer的答案 ):

 public static T DeepClone(T obj) { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } 

……然后打电话:

 ResultList clone = DeepClone(original); 

扩展@ Georgi-it,我不得不修改他的代码来处理其类型inheritanceList的属性:

 public static class ObjectCloner { public static T Clone(object obj, bool deep = false) where T : new() { if (!(obj is T)) { throw new Exception("Cloning object must match output type"); } return (T)Clone(obj, deep); } public static object Clone(object obj, bool deep) { if (obj == null) { return null; } Type objType = obj.GetType(); if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) { return obj; } List properties = objType.GetProperties().ToList(); if (deep) { properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); } object newObj = Activator.CreateInstance(objType); foreach (var prop in properties) { if (prop.GetSetMethod() != null) { var proceed = true; if (obj is IList) { var listType = obj.GetType().GetProperty("Item").PropertyType; if (prop.PropertyType == listType) { proceed = false; foreach (var item in obj as IList) { object clone = Clone(item, deep); (newObj as IList).Add(clone); } } } if (proceed) { object propValue = prop.GetValue(obj, null); object clone = Clone(propValue, deep); prop.SetValue(newObj, clone, null); } } } return newObj; } } 

这是我需要和编写的东西,它使用reflection来复制每个属性(如果指定,则使用私有属性)

 public static class ObjectCloner { public static T Clone(object obj, bool deep = false) where T : new() { if (!(obj is T)) { throw new Exception("Cloning object must match output type"); } return (T)Clone(obj, deep); } public static object Clone(object obj, bool deep) { if (obj == null) { return null; } Type objType = obj.GetType(); if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) { return obj; } List properties = objType.GetProperties().ToList(); if (deep) { properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); } object newObj = Activator.CreateInstance(objType); foreach (var prop in properties) { if (prop.GetSetMethod() != null) { object propValue = prop.GetValue(obj, null); object clone = Clone(propValue, deep); prop.SetValue(newObj, clone, null); } } return newObj; } }