Клонирование объектов без сериализации - PullRequest
6 голосов
/ 20 января 2012

Я нашел множество решений здесь, в SO, и в других случаях, которые имеют дело с глубоким клонированием объекта посредством сериализации / десериализации (в память и обратно).

Требуется, чтобы клонируемые классы отмечались * 1003.*.Мне случается, что мои классы (в большинстве своем) помечены [DataContract], потому что я использую DataContractSerializer для сериализации в XML.

Я только ввел атрибут [Serializable] из-за необходимости глубокого клонирования некоторыхиз этих экземпляров класса.Однако теперь что-то случилось с сериализацией / десериализацией через DCS, потому что она больше не работает - ошибки, связанные с ожиданием другого XML-элемента при десериализации.Если я удалю [Serializable], ошибки исчезнут.

Какие у меня варианты?Я просто хочу глубоко клонировать мои объекты как можно проще.

Ответы [ 3 ]

11 голосов
/ 20 января 2012

Это работает

    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 голос
/ 30 августа 2018

Вот как это использовать:

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;
}
1 голос
/ 13 октября 2016

Сериализация и десериализация Json должны работать, для этого не требуется, чтобы классы имели сериализованную аннотацию.

public static T DeepCopy<T>(this T source)
{
    return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...