克隆没有序列化的对象

时间:2012-01-19 23:47:10

标签: c# xml-serialization clone datacontractserializer

我在SO处找到了许多解决方案,而且是通过序列化/反序列化(进入内存和返回)处理对象的深层克隆。

要求克隆的类标有[Serializable]。我碰巧将我的类(其中大多数)标记为[DataContract],因为我使用DataContractSerializer来序列化为XML。

我只引入了[Serializable]属性,因为需要深度克隆其中一些类实例。但是,现在通过DCS进行序列化/反序列化的事情发生了,因为它不再起作用 - 关于在反序列化时期望不同的XML元素的错误。如果我删除[Serializable]错误消失了。

我有什么选择?我只想尽可能简单地克隆我的对象。

3 个答案:

答案 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;
}