Клонируйте целый граф объектов

При использовании этого кода для сериализации объекта:

public object Clone()
{
    var serializer = new DataContractSerializer(GetType());
    using (var ms = new System.IO.MemoryStream())
    {
        serializer.WriteObject(ms, this);
        ms.Position = 0;
        return serializer.ReadObject(ms);
    }
}

Я заметил, что это не копирует отношения. Там какой-либо путь состоит в том, чтобы заставить это произойти?

6
задан SilverlightFox 4 March 2014 в 16:06
поделиться

4 ответа

Просто используйте перегрузку конструктора, который принимает preserveObjectReferences, и установите его в true:

using System;
using System.Runtime.Serialization;

static class Program
{
    public static T Clone<T>(T obj) where T : class
    {
        var serializer = new DataContractSerializer(typeof(T), null, int.MaxValue, false, true, null);
        using (var ms = new System.IO.MemoryStream())
        {
            serializer.WriteObject(ms, obj);
            ms.Position = 0;
            return (T)serializer.ReadObject(ms);
        }
    }
    static void Main()
    {
        Foo foo = new Foo();
        Bar bar = new Bar();
        foo.Bar = bar;
        bar.Foo = foo; // nice cyclic graph

        Foo clone = Clone(foo);
        Console.WriteLine(foo != clone); //true - new object
        Console.WriteLine(clone.Bar.Foo == clone); // true; copied graph

    }
}
[DataContract]
class Foo
{
    [DataMember]
    public Bar Bar { get; set; }
}
[DataContract]
class Bar
{
    [DataMember]
    public Foo Foo { get; set; }
}
16
ответ дан 8 December 2019 в 12:58
поделиться

Вам понадобится двоичный сериализатор для сохранения идентичности объектов на этапе сериализации / десериализации.

0
ответ дан 8 December 2019 в 12:58
поделиться

Для выполнения глубокого клонирования вы можете рассмотреть возможность использования двоичного сериализатора:

public static object CloneObject(object obj)
{
    using (var memStream = new MemoryStream())
    {
        var binaryFormatter = new BinaryFormatter(
             null, 
             new StreamingContext(StreamingContextStates.Clone));
        binaryFormatter.Serialize(memStream, obj);
        memStream.Seek(0, SeekOrigin.Begin);
        return binaryFormatter.Deserialize(memStream);
    }
}
1
ответ дан 8 December 2019 в 12:58
поделиться

Либо аннотируйте свои классы с помощью [DataContract] , либо добавьте дочерние типы в конструктор DatacontractSerializer.

var knownTypes = new List<Type> {typeof(Class1), typeof(Class2), ..etc..};
var serializer = new DataContractSerializer(GetType(), knownTypes);
1
ответ дан 8 December 2019 в 12:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: