Сериализация и десериализация нескольких объектов с помощью DataContractSerializer

#c# #serialization #datacontractserializer

#c# #сериализация #datacontractserializer

Вопрос:

Как мне сериализовать и десериализовать несколько объектов с помощью DataContractSerializer? Сериализация проходит нормально, однако во время десериализации я получаю сообщение об ошибке

«Операция сериализации завершилась неудачно. Причина: произошла ошибка десериализации объекта сериализации типа.Человек. Существует несколько корневых элементов. «

В сообщении об ошибке четко указано, что в сериализованном документе отсутствует корневой элемент. Но как мне это преодолеть?

Вот код:

 [DataContract]
class Person {
    [DataMember(Name = "CustName")]
    internal string Name;
    public Person(string n) {Name = n;}
}

class Program {
    public static void Main() {
            WriteObject("d:\temp\DataContractExample.xml" , "Mary");
            WriteObject("d:\temp\DataContractExample.xml", "Joe");
            ReadObject("d:\temp\DataContractExample.xml");
    }

    public static void WriteObject(string path, string name) {
        Person p1 = new Person(name);
        FileStream fs = new FileStream(path, FileMode.Append);
        XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs);
        DataContractSerializer ser =  new DataContractSerializer(typeof(Person));
        ser.WriteObject(writer, p1);

        writer.Close();
        fs.Close();
    }
    public static void ReadObject(string path) {
        FileStream fs = new FileStream(path, FileMode.OpenOrCreate);
        XmlDictionaryReader reader =
            XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());

        DataContractSerializer ser = new DataContractSerializer(typeof(Person));

        // Deserialize the data and read it from the instance.
        Person[] newPerson = (Person[])ser.ReadObject(reader);
        Console.WriteLine("Reading this object:");
        Console.WriteLine(String.Format("{0}", newPerson[0].Name));
        fs.Close();
    }
  

Когда я читаю из DataContractSerializer, ser.readObject(reader), я получаю исключение, о котором я упоминал выше.
Возможно ли создать корневой элемент при сохранении нескольких объектов с помощью DataContractSerializer?

Комментарии:

1. Однако, если формат хранилища можно изменить, обратите внимание, что некоторые форматы можно безопасно добавлять; дайте мне знать, если вас может заинтересовать аналогичный пример с использованием другого формата данных (но который работает)

2. Также обратите внимание — вы пишете (отдельно) два Person экземпляра и пытаетесь десериализовать Person[] — но это имеет совсем другой макет

3. Да, Марк! О каких других форматах хранения вы говорите. Мне помогут любые указатели. Я создаю решение для хранения данных для иерархии рабочего процесса. Поэтому мне нужно динамически добавлять, изменять и удалять элементы.

4. добавление выполняется легко; изменение и удаление из середины файла обычно означает перезапись всего файла

5. Примечание: если вы можете сериализовать a List<Person> в первую очередь, это может быть не проблема (т. Е. Она будет работать с DataContractSerializer)

Ответ №1:

DataContractSerializer работает с XML-документами, поэтому ожидает один элемент верхнего уровня. Самым простым подходом было бы сериализовать a List<Person> , что должно избежать этого. Вы также можете добавить внешний элемент вручную, возможно, используя XmlReader и ReadSubtree во время сериализации (хотя обратите внимание: это ужасно тяжелая работа).

Однако самый простой вариант — просто сериализовать a List<Person> с самого начала и десериализовать как a List<Person> — тогда это будет один XML-фрагмент, так что это не расстроит десериализатор.