Как сериализовать классы, которые не были предназначены для сериализации?
Мне нужно сохранить некоторые классы и структуры данных в файл. Моим первым рефлексом было использовать XML или двоичную сериализацию, но это превращается в кошмар. У меня есть набор классов, которые не должны были быть сериализованы (частные сеттеры, без параметрических конструкторов, без атрибута сериализации, словарей и т. д.). Учитывая, что я не могу изменить эти классы, что мне делать? Есть ли обходной путь и все еще использовать сериализацию?
Мне придется написать все код для записи свойств, коллекций и т. д.?
7 ответов
используйте JavaScriptSerializer. Это в системе.Сеть.Скрипт.Пространство имен сериализации и реализуется в 3.5 framework в системе.Сеть.Увеличение.сборка 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 );
}
}
звучит как работа для... суррогаты сериализации!
на http://msdn.microsoft.com/en-us/magazine/cc188950.aspx
обзор.
Я бы использовал инструмент генерации кода (mygeneration, T4, whatever) для генерации DTOs для сериализации...
не простой обходной путь.
вероятно, вы хотите только сериализовать / десериализовать поля (частные и общедоступные) в классах и сделать это рекурсивно. Вероятно, вам нужно будет использовать отражение, чтобы добраться до них. Не удаляйте/сериализуйте свойства, потому что при установке значения свойства могут быть побочные эффекты. Вам также придется рекурсивно де / сериализовать все поля, которые являются объектами. Проблема в том, чтобы знать, где остановиться.
вам придется сделать некоторые большие догадки о том, как десериализовать сериализованный объект с помощью отражения. Я должен предположить, что некоторые поля этих объектов содержат ссылки на другие объекты, и вы также должны знать, как пройти все это.
кроме того, вам придется вызвать параметризованные конструкторы и надеяться, что вы не делаете слишком много повреждений при настройке полей с отражением.
короче говоря, вам может быть лучше создать специальный набор классов-оболочек что делает наилучшую форму повторного создания ваших проприетарных классов из сериализованного формата. Ваши специальные классы могут быть затем сделаны сериализуемыми. Это будет непростая задача.
тем не менее, code gen может упростить задачу идентификации всех полей в классах.
другой вариант-использовать шаблон адаптера.
хорошая новость заключается в том, что вам не придется изменять исходный класс. Плохая новость заключается в том, что вы, вероятно, напишете в два раза больше кода, чем существует в первом "неизменяемом" классе.
вы получите 2 новых класса: адаптер и новый класс serializble.
идея заключается в том, что адаптер знает, как создать serizliable класс, исследуя несериализуемый класс. Идти другим путем. (Serializable к unserializable) вы можете снова использовать адаптер (конечно, здесь я предполагаю, что ваши личные сеттеры на самом деле установить через конструктор с параметрами).
в этом есть две отдельные части:
- извлечение/установка данных
- хранение/чтение из файла (или другое место)
для первой части, если вы не можете изменить классы, которые хотите сериализовать/десериализовать, вы действительно просто остались с глубокой копией через отражение.
для сериализации просмотрите каждый член класса, хранящий его значение.
использовать тот, который вы хотите сохраните его, например XML, и запишите эти значения на диск.
для десериализации прочитайте значения из файла, создайте новый экземпляр объекта и используйте отражение, чтобы установить все значения.
Если вы получите / установите все члены, у вас будет объект, который находится в одинаковом состоянии. (Вам может потребоваться рекурсивно пройти все ваши объекты, если у вас есть сложные члены.)
Как вы храните данные на диске, XML или двоичных работы. Если вы хотите увидеть его и сделать его читаемым человеком, а затем перейти к XML. (Я бы рекомендовал это для вашего первоначального удара по нему, так как это сделает отладку намного проще.)
Это действительно зависит от масштаба вашей проблемы и производительность, необходимую.
Если у вас есть 1 класс проблем, я бы просто написал суррогатный класс, который может сериализовать/десериализовать этот класс. Если вы говорите о 100 классах, вам, вероятно, нужно использовать структуру сериализации, которая поддерживает все тонкости. Никакая параметрическая конструкция не является кошмаром, независимо от того, какую структуру сериализации вы пишете или используете, вам нужно будет знать передние параметры, чтобы перейти к конструктор. Частные сеттеры / словари / списки и т. д. Не слишком большая проблема.
Я написал мини-сериализации framework для медиа-браузера, который является BSD. Мое внимание было сосредоточено на производительности, но методы, которые я использую могут быть адаптированы к вашей проблеме. Аналогично методам, используемым в протокол буферы может использоваться.
Если производительность не важна вообще, довольно тривиальная структура сериализации может быть закодирована довольно быстро, которая использует отражение, вещи становятся трудными, когда вы пытаетесь сохранить вещь в рабочем состоянии.