Какая сериализация является наиболее гибкой для .СЕТЕВЫХ объектов, но простой в реализации?
-
01-07-2019 - |
Вопрос
Я хотел бы сериализовать и десериализовать объекты, не беспокоясь обо всем графе классов.
Гибкость - это ключ к успеху.Я хотел бы иметь возможность сериализовать любой переданный мне объект без полных атрибутов, необходимых для всего графа объектов.
Это означает, что двоичная сериализация не является опцией, поскольку она работает только с другими платформами .NET.Я бы также хотел, чтобы что-то читалось человеком и, следовательно, расшифровывалось программой управления и другими переводчиками.
Я обнаружил проблемы с использованием сериализаторов DataContract, JSON и XML.
- Большинство из этих ошибок, по-видимому, связаны с сериализацией списков / словарей (т. е. XML-Сериализуемый Универсальный словарь).
- "Добавьте любые типы, неизвестные статически , в список известных типов - например, с помощью атрибута KnownTypeAttribute или добавив их в список известных типов, переданных в DataContractSerializer."
Пожалуйста, основывайте свои ответы на реальном опыте, а не на теории или прочтении статьи.
Решение
Рассматривали ли вы возможность сериализации в JSON вместо XML?
Json.NET имеет действительно мощный и гибкий сериализатор, который не имеет проблем с хэш-таблицами / универсальными словарями и не требует каких-либо конкретных атрибутов.Я знаю, потому что я это написал :)
Это дает вам массу возможностей управления с помощью различных опций сериализатора и позволяет переопределить способ сериализации типа, создав для него JsonConverter.
На мой взгляд, JSON более удобочитаем для человека, чем XML и Json.NET предоставляет возможность писать красиво отформатированный JSON.
Наконец, проект имеет открытый исходный код, так что вы можете войти в код и внести изменения, если вам нужно.
Другие советы
Насколько я помню, это работает примерно так со свойством:
[XmlArray("Foo")]
[XmlArrayItem("Bar")]
public List<BarClass> FooBars
{ get; set; }
Если бы вы сериализовали это, то получили бы что-то вроде:
<Foo>
<Bar />
<Bar />
</Foo>
Конечно, мне, вероятно, следует довериться экспертам.Вот больше информации от MS: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx
Дай мне знать, если у тебя это получится.
Исходя из ваших требований, лучше всего использовать сериализацию Xml.
Какие проблемы возникают у вас с коллекциями при сериализации?Если вы имеете в виду, что не знаете, какие атрибуты использовать в списке или что-то подобное, вы можете попробовать использовать атрибут XmlArray в вашем свойстве.Вы определенно можете сериализовать коллекцию.
IntermediateSerializer в XNA Framework чертовски крут.Вы можете найти множество руководств по его использованию по адресу http://blogs.msdn.com/shawnhar
Сериализация SOAP работала хорошо для меня, даже для объектов, не помеченных [Serializable]
У вас возникнут проблемы с сериализацией коллекции, если объекты в коллекции содержат какие-либо ссылки на другие объекты в той же коллекции.Если существует какой-либо тип двойного наведения, в конечном итоге вы создаете мультикарту, которая не может быть сериализована.При каждой проблеме, с которой я когда-либо сталкивался при сериализации пользовательской коллекции, это всегда было связано с какой-то добавленной функциональностью, которая мне была нужна, которая прекрасно работала как часть "типичного" клиент-серверного приложения, а затем с треском проваливалась как часть приложения потребитель-поставщик-сервер.
Поместите все классы, которые вы хотите сериализовать, в отдельную сборку, а затем используйте инструмент sgen для создания сборки сериализации для сериализации в XML.Используйте атрибуты XML для управления сериализацией.
Если вам нужно настроить сборку сериализации (и вы будет это необходимо для поддержки классов, которые не являются IXmlSerializable, и классов, содержащих абстрактные узлы), затем проинструктируйте sgen выгрузить исходный код в отдельный файл, а затем добавить его в ваше решение.Затем вы можете изменить его по мере необходимости.
http://msdn.microsoft.com/en-us/library/bk3w6240 (ПРОТИВ 80).aspx
FWIW, мне удалось сериализовать весь фреймворк AdsML (более 400 классов), используя эту технику.Это действительно потребовало большой ручной настройки, но с этим ничего не поделаешь, если учесть размер фреймворка.(Я использовал отдельный инструмент для перехода с XSD на C #)
Я согласен, что методы сериализации на основе DataContract (в JSON, XML и т.д.) Немного сложнее, чем хотелось бы.
Если вы пытаетесь получить JSON, проверьте http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
Это часть расширений MS AJAX.По общему признанию, он помечен как устаревший в .NET 3.5, но Скоттгу упоминает об этом в своем комментарии в блоге здесь (http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx#4301973), что он не уверен, почему, и это должно поддерживаться немного дольше.
Самое простое, что можно сделать, это пометить ваши объекты атрибутом Serializable, а затем использовать двоичный форматировщик для обработки сериализации.Весь граф классов не должен быть проблемой при условии, что все содержащиеся в нем объекты также помечены как сериализуемые.
Возможно, более эффективным способом была бы сериализация с использованием BinaryFormatter
Как скопировано с http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class Serializer
{
public Serializer()
{
}
public void SerializeObject(string filename,
ObjectToSerialize objectToSerialize)
{
Stream stream = File.Open(filename, FileMode.Create);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, objectToSerialize);
stream.Close();
}
public ObjectToSerialize DeSerializeObject(string filename)
{
ObjectToSerialize objectToSerialize;
Stream stream = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
objectToSerialize =
(ObjectToSerialize)bFormatter.Deserialize(stream);
stream.Close();
return objectToSerialize;
}
}
Для обеспечения совместимости мы всегда использовали сериализацию Xml и следили за тем, чтобы наш класс был разработан с нуля, чтобы делать это правильно.
Мы создаем документ XSD-схемы и генерируем набор классов на основе этого, используя XSD.exe.Это генерирует частичные классы, поэтому затем мы создаем набор соответствующих частичных классов, чтобы добавить дополнительные методы, которые помогут нам заполнить классы и использовать их в нашем приложении (поскольку они ориентированы на сериализацию и десериализацию и иногда их немного сложно использовать).
Вам следует использовать NetDataContractSerializer.Он охватывает любой тип объектного графа и поддерживает дженерики, списки, полиморфизм (атрибут KnownType здесь не нужен), рекурсию и т.д.Единственным недостатком является то, что вы должны пометить все свои классы атрибутами [Serializable] / [DataContract], но опыт показывает, что вам все равно придется выполнять какую-то ручную тонкую настройку, поскольку не все члены должны сохраняться.Также он сериализуется в Xml, хотя его читабельность сомнительна.
У нас были те же требования, что и у вас, и мы выбрали это решение.