Подтвердить что ты не робот

Разница между атрибутом DataContract и атрибутом Serializable в .net

Я пытаюсь создать глубокий клон объекта, используя следующий метод.

    public static T DeepClone<T>(this T target)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, target);
            stream.Position = 0;
            return (T)formatter.Deserialize(stream);
        }
    } 

Этот метод требует объекта, который является Сериализованным, то есть объектом класса, который имеет на нем атрибут "Serializable" . У меня есть класс, который имеет атрибут "DataContract" , но метод не работает с этим атрибутом. Я думаю, что "DataContract" также является сериализатором, но, возможно, отличается от типа "Serializable" .

Может ли кто-нибудь объяснить мне разницу между ними? Также, пожалуйста, дайте мне знать, возможно ли создать глубокий клик объекта с одним атрибутом, который выполняет работу как с атрибутом "DataContract" , так и с "Serializable" или может быть другим способом создания глубокого изображения?

Пожалуйста, помогите!

4b9b3361

Ответ 2

DataContract используется в WCF, поэтому .NET 3.0+. В .net 2.0 или ниже нет атрибута DataContract, DataMember, только Serializable.

Как сказал Oded, если вы хотите использовать BinaryFormatter, вам нужно украсить тип Serializable.

Ответ 3

Я однажды осмотрел структуру объекта через Reflection, чтобы найти все сборки, необходимые для десериализации, и сериализовать их вместе для начальной загрузки.

С небольшим количеством работы можно было создать аналогичный метод для глубокого копирования. В основном вам нужен рекурсивный метод, который проводит по Слову для обнаружения циклических ссылок. Внутри метода вы проверяете все поля примерно так:

private void InspectRecursively(object input,
    Dictionary<object, bool> processedObjects)
{
  if ((input != null) && !processedObjects.ContainsKey(input))
  {
    processedObjects.Add(input, true);

    List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
        BindingFlags.Public | BindingFlags.NonPublic );
    foreach (FieldInfo field in fields)
    {
      object nextInput = field.GetValue(input);

      if (nextInput is System.Collections.IEnumerable)
      {
        System.Collections.IEnumerator enumerator = (nextInput as
            System.Collections.IEnumerable).GetEnumerator();

        while (enumerator.MoveNext())
        {
          InspectRecursively(enumerator.Current, processedObjects);
        }
      }
      else
      {
        InspectRecursively(nextInput, processedObjects);
      }
    }
  }
}

Чтобы получить работу, вам нужно добавить выходной объект и что-то вроде System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type) для создания самой мелкой копии (даже без копирования ссылок) каждого значения поля. Наконец, вы можете установить каждое поле с чем-то вроде field.SetValue(input, output)

Однако эта реализация не поддерживает зарегистрированные обработчики событий, которые являются _ un _supported путем десериализации. Кроме того, каждый объект в иерархии будет разбит, если его конструктор класса должен инициализировать что-либо, кроме установки всех полей. Последняя точка работает только с сериализацией, если класс имеет соответствующую реализацию, например. метод, отмеченный [OnDeserialized], реализует ISerializable,....