Pull to refresh

Comments 31

Попробуйте простую серилизацию классов. На члены класса можно повесить различные XML атрибуты.
XmlSerializer serializer = new XmlSerializer(typeof_object);
fs = new FileStream(FileName, FileMode.Create, System.IO.FileAccess.ReadWrite);
XmlWriter writer = new XmlTextWriter(fs, System.Text.Encoding.Unicode);
serializer.Serialize(writer, obj);


Десерилизация выполняется тоже в 4 строчки кода.
XmlSerializer serializer = new XmlSerializer(typeof_object);
fs = new FileStream(FileName, FileMode.Create, System.IO.FileAccess.ReadWrite);
XmlWriter writer = new XmlTextWriter(fs, System.Text.Encoding.Unicode);
serializer.Serialize(writer, obj);
А если у вас получатель этого документа написан на
Java/ JS/ WhatEverNotOnDotNet?
Эта штука серилизует как описано атрибутами в классе. Если нужно использовать XML вам — вы знаете как сохранить и загрузить. Автор же пишет, что он их заменял конфигурационными файлами.

По мне так xml очень удобная вещь для хранения много чего — настроек, данных (не большого объема). Для передачи по сети тоже очень подходит. Ajax там и WCF.
>Ajax там

Для Ajax XML — это точно плохой выбор. Ajax должен быть быстрым и легким, дублирование имен полей там явно лишнее. Для Ajax стандартом уже вроде как JSON стал.
Без разницы на чем написана получатель, там самый обычный XML, без всяких прибамбасов.

Так будет выглядить сериализированный ХМЛ, класс Teacher

<Teacher xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:/
/www.w3.org/2001/XMLSchema">
  <Id>6eb64959-c267-4dbb-94cc-4163f3fe7a28</Id>
  <FirstName>Maria</FirstName>
  <LastName>Ivanovna</LastName>
</Teacher>


Да, такой способ подходит, но вы здесь забыли упомянуть что для этого потребуется создать объект.
А есть множество случаев когда XML конструируется из составных объектов, создавать только для сериализации объект — не вариант, в том случае, если получатель будет другой.
Либо когда данные запрашиваются у БД, можно сразу их трансформировать в XML без загрузки в промежуточные объекты.

Собственно, где мне пришлось это применять: на веб-сервисах, где источником является MS SQL база на выходе нужно получить XML, который будут использовать клиентское iPhone приложение и Windows Forms.
Собственно, где мне пришлось это применять: на веб-сервисах, где источником является MS SQL база на выходе нужно получить XML, который будут использовать клиентское iPhone приложение и Windows Forms.

MS SQL начиная с 2005 отлично умеет конструировать и возвращать XML любой сложности. так же как и извлекать данные из xml полученного на вход.
или у вас так и было, а проблема была в парсинге XML приложением?
Либо когда данные запрашиваются у БД, можно сразу их трансформировать в XML без загрузки в промежуточные объекты.

XDocument тоже полностью грузит в память. Разнице невелика.
XmlSerializer требует, чтобы сборка, содержащая сериализуемый тип, находилась физически на диске. Иногда мешает.
да? разве не достаточно чтобы сборка была уже загружена в память, не важно каким образом? надо бы проверить, полено знать о таких граблях заранее :")
Вот важно почему-то. После Assembly.Load(byte[]) XmlSerializer работать отказывается.
Я потратил несколько часов на поиск ответа «почему не сериализуется», потому что эта сволочь (XmlSerializer) даже не соизволила сказать, чем именно недовольна.
да, действительно. интернет полон описаний проблем с dynamic assembly и разнообразных workaround'ов к ним. в будущем буду иметь в виду. И хотя до сих пор ни разу с этой проблемой не столкнулся знать о ней не помешает. Спасибо :)
XMLSerializer эмиттит код сериализации. А текущий компилятор шарпа не умеет компилировать в памяти, только из сборки на диске. Отсюда тебование на доступ к временной директории, где будет сгенерена сборка с кодом сериализации. Плюс — вторая и все последующие сериализации выполняются моментально, минус — необходимость прав на запись во временную папку.
Речь не об этом, а о том, что XMLSerializer'у нужно, чтобы сборка, содержащая сериализуемый тип, лежала на диске.
Я уже как-то делал подобное, только что перепроверил. Ненужно.


var asm = Assembly.Load(File.ReadAllBytes(@"C:\..\AnotherLib.dll"));
var t = asm.GetTypes().First(x => x.Name == "Teacher");
var serializer = new XmlSerializer(t);
serializer.Serialize(Console.Out, Activator.CreateInstance(t));

Этот код отработал без проблем.
Deserialize не работает.
На собранном суррогатном примере всё работает. В «настоящем», в случае динамической загрузки — нет, в случае статической — всё ок. Надо копать, что влияет.
У меня связка Serialize/Deserialize работает. Правда у меня нет проблем с правами. Все в FullTrust режиме. Я сколняюсь что у вас проблемы с правами.

По ходу, наверное уже стоит пользовать DataContractSerializer, он как бы и побыстрее, и не требует временных папок/ассемблей. Правда наверное менее гибкий.
  1.         public String Save()
  2.         {
  3.             String retVal = String.Empty;
  4.             MemoryStream ms = new MemoryStream();
  5.  
  6.             TextWriter sw = null;
  7.  
  8.             try
  9.             {
  10.                 XmlSerializer ser = new XmlSerializer(this.GetType());
  11.  
  12.                 sw = new StreamWriter(ms, Encoding.UTF8);
  13.  
  14.                 ser.Serialize(sw, this);
  15.             }
  16.             catch (Exception ex)
  17.             {
  18.                 throw ex;
  19.             }
  20.             finally
  21.             {
  22.                 ms.Seek(0, SeekOrigin.Begin);
  23.                 StreamReader sr = new StreamReader(ms);
  24.  
  25.                 retVal = sr.ReadToEnd();
  26.                 retVal = retVal.Replace(Environment.NewLine, "");
  27.  
  28.                 if (sw != null)
  29.                     sw.Close();
  30.             }
  31.  
  32.             return retVal;
  33.         }
  34.  
  35.         public static void Load(string objectValue, out D retVal)
  36.         {
  37.             byte[] byteArray = Encoding.UTF8.GetBytes(objectValue);
  38.             MemoryStream ms = new MemoryStream(byteArray);
  39.  
  40.             XmlTextReader reader = new XmlTextReader(ms);
  41.  
  42.             try
  43.             {
  44.                 XmlSerializer ser = new XmlSerializer(typeof(D));
  45.  
  46.                 reader.Normalization = false;
  47.                 retVal = (D)ser.Deserialize(reader);
  48.             }
  49.             catch (Exception ex)
  50.             {
  51.                 throw ex;
  52.             }
  53.             finally
  54.             {
  55.                 if (reader != null)
  56.                     reader.Close();
  57.             }
  58.         }
  59.  
XML сериализация не всегда лучший вариант, как правило самый простой — да, но не всегда подходящий ;)
У меня было несколько ситуаций, когда надо было поддерживать две различные структуры xml документа для одного и того же документа как при сериализации, так и при десириализации. Решалось частично через XmlAttributeOvverides, но ясности коду это в итоге не прибавило. Так же иногда это было легче сделать просто «ручным» разбором или сохранением.
Так же был случай, когда надо было сериализовывать экземпляр класса из другой либы, в которой не было указано этих атрибутов (ну или просто они были указаны не так, как надо), решалось опять как правило через XmlAttributeOvverides или ручным генерированием XML.
Так же лично мне часто приходиться генерировать XML напрямую (например при формировании запроса), т.к. для того, что бы сгенерировать нужный XML на основе данных из каких то твоих классов и отослать его, не стоит делать отдельный класс представляющий отдельный XML (поди RequestClass), что бы потом создавать его на основе уже имеющихся и сериализовать затем.
Сериализация и просто работа с XML документами просто немного разные вещи (просто в примерах обычно показывают простую сериализацию), и признаться честно — XmlDocument менее удобный и менее читаемый, чем XDocument\XElement, хотя и у последнего есть свои минусы порой (в частности XmlDocument сохраняет оригинальный xml и всегда можно получить его часть через InnerXml, OuterXml).
Не помню, чтобы мне когда-либо приходилось вот так руками составлять xml-файл.
Необходимо получить такое сообщение:

На этом месте для данного xml-файла очень просится обычное действие: создать класс с нужными полями и сериализовать его в xml-файл.
Для сохранения настроек или состояния программы да, сериализация является наилучшим вариантом, но бывает когда обмен данными происходит с помощью XML, при чем структура которого очень сложна, тут как правило без «ручного» составления XML не обойтись.
ну и десериализировать можно не только документ целиком, но и ноду. т.ч. «городить сложный объект» вовсе не обязательно, достаточно нагородить только нужный кусок с которым и работать. а в большой и сложный документ этот кусок вставлять/извлекать с помощью Dom, так должно получать гораздо проще.
В моем приложении часто на основе моих классов, надо сформировать XML запрос к какому нибудь шлюзу. Работа с конкретным шлюзом реализуется с помощью отдельного класса, наследуемого от общего, т.е. везде этот XML запрос свой (хотя порой это даже не XML).
Можно конечно использовать XML сериализацию, но тогда надо для каждого такого класса (допустим Gate1… GateN) делать соответствующие классы запросов\ответов Gate1Request… GateNRequest\Gate1Response… GateNResponse. После этого внутри метода создать этот класс на основе входных параметров метода, и все это только что бы «красиво сериализовать стандартными средствами». Зачем если можно сразу начать формировать XML запрос «ручками»?
Спасибо, как раз искал, подобную статью, только для разбирания чужого документа (который сохраняют как раз вышеопомянутой серриализацией класса), доступа к исходникам нет. А писать тонну кода не хочется. Буду ждать следующую статью, про ток как разбирать документ.
А зачем статью ждать? :) Покурите МСДН на тему методов Element() и Elements() класса XElement, и будет вам счастье :)
Попробуйте ещё xsd.exe из .net sdk (позволяет сгенерировать классы по xml-документу или xsd-схеме, к ним уже можете применить описанный выше XmlSerializer).
Здесь небольшой референс по использованию: msdn.microsoft.com/en-us/library/x6c1kb0s(v=VS.100).aspx

Можете сохранить себе кучу времени при разборе большого числа сложных xml-документов. Но не забывайте, что кодогенерация — не всегда добро.
UFO landed and left these words here
Only those users with full accounts are able to leave comments. Log in, please.