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

Как сериализовать классы, которые не были предназначены для сериализации?

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

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

4b9b3361

Ответ 1

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

С помощью этого класса вы можете сериализовать любой POCO независимо от того, отмечен ли он как [Serializable] или нет. Ваша программа не обязательно должна быть веб-приложением для использования 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 );
  }
}

Ответ 3

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

Ответ 4

Не простой способ обхода.

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

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

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

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

Тем не менее, код gen мог бы упростить задачу определения всех полей в классах.

Ответ 5

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

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

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

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

Здесь шаблон подробно.

Ответ 6

Для этого есть две отдельные части:

  • извлечение/настройка данных
  • сохранение/чтение его из файла (или другого местоположения)

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

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

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

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

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

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

Ответ 7

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

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

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

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