我在SO处找到了许多解决方案,而且是通过序列化/反序列化(进入内存和返回)处理对象的深层克隆。
要求克隆的类标有[Serializable]
。我碰巧将我的类(其中大多数)标记为[DataContract]
,因为我使用DataContractSerializer
来序列化为XML。
我只引入了[Serializable]
属性,因为需要深度克隆其中一些类实例。但是,现在通过DCS进行序列化/反序列化的事情发生了,因为它不再起作用 - 关于在反序列化时期望不同的XML元素的错误。如果我删除[Serializable]
错误消失了。
我有什么选择?我只想尽可能简单地克隆我的对象。
答案 0 :(得分:11)
这有效
public static T DeepClone<T>(this T a)
{
using (MemoryStream stream = new MemoryStream())
{
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
dcs.WriteObject(stream, a);
stream.Position = 0;
return (T)dcs.ReadObject(stream);
}
}
答案 1 :(得分:1)
Json序列化和反序列化应该有效,它不要求类具有序列化注释。
public static T DeepCopy<T>(this T source)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
答案 2 :(得分:1)
这里是使用方法:
var oldList = new List<int>();
var newList = oldList.Clone();
使用以下方法:
public static T Clone<T>(this T o) where T : new()
{
return (T)CloneObject(o);
}
static object CloneObject(object obj)
{
if (ReferenceEquals(obj, null)) return null;
var type = obj.GetType();
if (type.IsValueType || type == typeof(string))
return obj;
else if (type.IsArray)
{
var array = obj as Array;
var arrayType = Type.GetType(type.FullName.Replace("[]", string.Empty));
var arrayInstance = Array.CreateInstance(arrayType, array.Length);
for (int i = 0; i < array.Length; i++)
arrayInstance.SetValue(CloneObject(array.GetValue(i)), i);
return Convert.ChangeType(arrayInstance, type);
}
else if (type.IsClass)
{
var instance = Activator.CreateInstance(type);
var fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var field in fields)
{
var fieldValue = field.GetValue(obj);
if (ReferenceEquals(fieldValue, null)) continue;
field.SetValue(instance, CloneObject(fieldValue));
}
return instance;
}
else
return null;
}