Как сериализовать классы, которые не были предназначены для сериализации? - PullRequest
12 голосов
/ 07 мая 2009

Мне нужно сохранить некоторые классы и структуры данных в файл. Моим первым рефлексом было использование XML или двоичной сериализации, но это превращается в кошмар. У меня есть набор классов, которые не предназначались для сериализации (частные установщики, без конструкторов без параметров, без атрибута сериализации, словарей и т. Д.). Учитывая, что я не могу изменить эти классы, что мне делать? Есть ли обходной путь, и все еще использовать сериализацию?

Должен ли я написать весь код для записи свойств, коллекций и т. Д.?

Ответы [ 7 ]

9 голосов
/ 07 мая 2009

Используйте JavaScriptSerializer. Он находится в пространстве имен System.Web.Script.Serialization и реализован в рамках 3.5 в сборке System.Web.Extensions.dll.

С помощью этого класса вы можете сериализовать любой POCO независимо от того, помечен он как [Сериализуемый] или нет. Ваша программа не обязательно должна быть веб-приложением, чтобы использовать сериализацию JSON. Вот пример:

public class Unserializable
{
  public int Age { get; set; }
  public int ID { get; set; }
  public string Name { get; set; }
}

public class Program
{
  static void Main()
  {
    var u = new Unserializable
            {
              Age = 40,
              ID = 2,
              Name = "Betty"
            };
    var jser = new JavaScriptSerializer();
    var jsonText = jser.Serialize( u );
    // next line outputs {"Age":40,"ID":2,"Name":"Betty"}
    Console.WriteLine( jsonText );
  }
}
7 голосов
/ 07 мая 2009

Звучит как работа для ... суррогатов сериализации!

Перейти к http://msdn.microsoft.com/en-us/magazine/cc188950.aspx

для обзора.

0 голосов
/ 07 мая 2009

Это действительно зависит от масштаба вашей проблемы и требуемой производительности.

Если у вас есть 1 класс задачи, я бы просто написал суррогатный класс, который может сериализовать / десериализовать этот класс. Если вы говорите о сотнях классов, вам, вероятно, нужно использовать платформу сериализации, которая поддерживает все тонкости. Никакая конструкция без параметров не является кошмаром. Независимо от того, какую среду сериализации вы пишете или используете, вам нужно заранее знать, какие параметры передаются конструктору. Частные сеттеры / словари / списки и т. Д. Не являются большой проблемой.

Я написал мини-сериализацию фреймворк для Media Browser, который является BSD. Я сосредоточился на производительности, но методы, которые я использую, могут быть адаптированы к вашей проблеме. Аналогичным образом можно использовать методы, используемые в буферах протокола Марка .

Если производительность вообще не важна, достаточно тривиальная структура сериализации может быть написана довольно быстро, с использованием отражения, и все становится трудно, когда вы пытаетесь сохранить ее производительность.

0 голосов
/ 07 мая 2009

Есть две отдельные части:

  1. извлечение / настройка данных
  2. сохранение / чтение из файла (или другого места)

Что касается первой части, если вы не можете изменить классы, которые хотите сериализовать / десериализовать, вам действительно просто нужно сделать глубокое копирование с помощью отражения.

Для сериализации просмотрите каждого члена класса, хранящего его значение.

Используйте любой носитель, на котором вы хотите сохранить его, например, XML, и запишите эти значения на диск.

Для десериализации прочитайте значения из файла, создайте новый экземпляр объекта и используйте отражение, чтобы установить все значения.

Если вы получите / установите все элементы, у вас будет объект, который находится в идентичном состоянии. (Возможно, вам понадобится рекурсивно просмотреть все ваши объекты, если у вас есть сложные члены.)

Что касается того, как вы храните данные на диске, то оба XML или двоичные файлы работают. Если вы хотите увидеть его и сделать его читаемым человеком, тогда используйте XML. (Я бы порекомендовал это для вашей первоначальной проверки, поскольку это значительно упростит отладку.)

0 голосов
/ 07 мая 2009

Другой вариант - использовать шаблон адаптера.

Хорошая новость заключается в том, что вам не придется менять исходный класс. Плохая новость заключается в том, что вы, вероятно, в конечном итоге напишите вдвое больше кода, чем существует в первом «неизменяемом» классе.

В итоге вы получите 2 новых класса: адаптер и новый сериализуемый класс.

Идея состоит в том, что адаптер знает, как создать класс serizliable, изучая класс unserializable. Чтобы пойти другим путем (от сериализуемого до не сериализуемого), вы можете снова использовать адаптер (конечно, здесь я предполагаю, что ваши частные сеттеры фактически устанавливаются через параметризованный конструктор).

Вот образец в деталях.

0 голосов
/ 07 мая 2009

Не простой обходной путь.

Возможно, вы хотите только сериализовать / десериализовать поля (private и public) в классах и делать это рекурсивно. Вы, вероятно, должны будете использовать отражение, чтобы добраться до них. Не де / сериализуйте свойства, потому что при установке значения свойства могут возникнуть побочные эффекты. Вам также придется рекурсивно де / сериализовать все поля, которые являются объектами. Проблема в том, чтобы знать, где остановиться.

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

Кроме того, вам придется вызывать параметризованные конструкторы и надеяться, что вы не наносите слишком много ущерба при установке полей с отражением.

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

Тем не менее, code gen может упростить задачу идентификации всех полей в классах.

0 голосов
/ 07 мая 2009

Я бы использовал инструмент генерации кода (mygeneration, T4, что угодно) для генерации DTO для сериализации ...

...