System.InvalidOperationException не было обработано — сериализация XMl C#

Я сделал XML-документ с помощью XML-сериализации.

Это выглядит так

<?xml version="1.0" encoding="utf-8"?>
<Course xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <courseName>Comp 1510</courseName>
  <backgroundColor>#ffffff</backgroundColor>
  <fontColor>#ffffff</fontColor>
  <sharingKey>ed35d1f8-6be1-4f87-b77f-c70298e5abbb</sharingKey>
  <task type="Assignment">
    <taskName>First Task</taskName>
    <description>description</description>
    <taskDueDate>2010-01-24T12:41:20.0321826-08:00</taskDueDate>
    <weight xsi:nil="true" />
    <beforeDueDateNotification>30</beforeDueDateNotification>
    <outOf>50.4</outOf>
  </task>
</Course>

Мой код, чтобы сделать это

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    [XmlRoot("Course")]
    public class MyWrapper 
    {
        public MyWrapper()
        {
            TaskList = new List<Tasks>();
        }

        [XmlElement("courseName")]
        public string CourseName { get; set; }

        [XmlElement("backgroundColor")]
        public string BackgroundColor { get; set; }

        [XmlElement("fontColor")]
        public string  FontColor { get; set; }

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }

        [XmlElement("task")]
        public List<Tasks> TaskList { get; set; }

    }

public class Tasks
{
    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlElement("taskName")]
    public string TaskName { get; set; }

    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("taskDueDate")]
    public DateTime TaskDueDate { get; set; }

    [XmlElement("weight")]
    public decimal? Weight { get; set; }

    [XmlElement("beforeDueDateNotification")]
    public int BeforeDueDateNotification { get; set; }

    [XmlElement("outOf")]
    public decimal? OutOf { get; set; }

}

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            MyWrapper wrap = new MyWrapper();
            wrap.CourseName = "Comp 1510";
            wrap.FontColor = "#ffffff";
            wrap.BackgroundColor = "#ffffff";
            wrap.SharingKey = Guid.NewGuid();

            Tasks task = new Tasks()
            {
                TaskName = "First Task",
                Type = "Assignment",
                TaskDueDate = DateTime.Now,
                Description = "description",
                BeforeDueDateNotification = 30,
                OutOf = 50.4M
            };

            wrap.TaskList.Add(task);
            SerializeToXML(wrap);

           var grab = DeserializeFromXML();

           foreach (var item in grab)
           {

           }
        }

        static public void SerializeToXML(MyWrapper list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
            TextWriter textWriter = new StreamWriter(@"C:\New folder\test.xml");
            serializer.Serialize(textWriter, list);
            textWriter.Close();
        }

        static List<MyWrapper> DeserializeFromXML()
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
            TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
            List<MyWrapper> tasks;
            tasks = (List<MyWrapper>)deserializer.Deserialize(textReader);
            textReader.Close();

            return tasks;
        }
    }
}

Теперь, когда я пытаюсь десериализовать его, я получаю эту ошибку

System.InvalidOperationException was unhandled
  Message="There is an error in XML document (2, 2)."
  Source="System.Xml"
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
       at ConsoleApplication1.Program.DeserializeFromXML() in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 55
       at ConsoleApplication1.Program.Main(String[] args) in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 34
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidOperationException
       Message="<Course xmlns=''> was not expected."
       Source="ap72r7cf"
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read5_ArrayOfMyWrapper()
       InnerException: 

Я не уверен, почему это происходит.

Некоторые побочные вопросы — ответьте, пожалуйста, после того, как будет дан ответ на основную проблему

Я не хотел создавать новый пост на форуме по этим 2 вопросам, если только мне не нужно.

  1. Почему важно присвоить ему тип объекта? Например, почему бы не сделать все поля строками?

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }
    

Это только потому, что при десериализации вы получите в этом случае Guid, чтобы позже вам не пришлось преобразовывать его из строки в Guid?

Если это правильно, как насчет того, если вы получите файл xml от кого-то другого и захотите его десериализовать, как вы узнаете, какие объекты из него получатся? Например, откуда вы знаете, что мой «OutOf» на самом деле является типом десятичного числа, допускающего значение NULL? На самом деле, откуда C# знает об этом? Я не вижу ничего, что могло бы намекнуть, что это тип.

  1. Когда я получаю его для фактической сериализации, мне интересно, как мне сделать цикл foreach. Так как я хочу просмотреть каждый из списка объектов «MyWrapper». Но в MyWrapper есть коллекция объектов Task. Итак, мне нужно сделать цикл for внутри моего цикла foreach, чтобы добраться до него? Или есть лучший способ?

Спасибо


person chobo2    schedule 24.01.2010    source источник


Ответы (2)


Вы пытаетесь сериализовать один экземпляр MyWrapper, а затем десериализовать его как список. Если вы придерживаетесь того или иного пути (в любом случае), он работает нормально. Например:

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        // Create single-element list
        serializer.Serialize(textWriter, new List<MyWrapper>{wrapper});
    }
}

static List<MyWrapper> DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (List<MyWrapper>)deserializer.Deserialize(textReader);
    }
}

или (для одного элемента):

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        serializer.Serialize(textWriter, wrapper);
    }
}

static MyWrapper DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (MyWrapper)deserializer.Deserialize(textReader);
    }
}

Просто нужно быть последовательным, вот и все.

person Jon Skeet    schedule 24.01.2010
comment
Ага. Я просто скопировал и вставил из учебника, над которым я работал, и, думаю, забыл, что у них нет такого класса-оболочки, который я использую. - person chobo2; 25.01.2010

Ну, я думаю, проблема в том, что вы сериализуете один MyWrapper, но пытаетесь десериализовать List<MyWrapper>

Это не сработает - вы сериализуете один объект в свой файл, вы получите один объект MyWrapper при десериализации из этого файла.

Измените десериализацию на:

    static MyWrapper DeserializeFromXML()
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
        TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
        MyWrapper tasks = (MyWrapper)deserializer.Deserialize(textReader);
        textReader.Close();
        return tasks;
    }

и все должно работать снова.

person marc_s    schedule 24.01.2010
comment
Да, похоже, это помогло. Вы знаете что-нибудь о моих других 2 вопросах? - person chobo2; 25.01.2010