3

I have the following xml file:

<MyConfig>
  <Item a1="Attrib11" a2="Attrib21" a3="Attrib31" />
  <Item a1="Attrib12" a2="Attrib22" a3="Attrib32" />
</MyConfig>

I load it in using the following helper methods:

public static T Load<T>(string path)
{
    XmlSerializer xml = new XmlSerializer(typeof(T));

    using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
    using (StreamReader sr = new StreamReader(fs))
    {
        return (T)xml.Deserialize(sr);
    }
}

public static void Save<T>(string path, T contents)
{
    XmlSerializer xml = new XmlSerializer(typeof(T));

    using (FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
    using (StreamWriter sw = new StreamWriter(fs))
    {
        xml.Serialize(sw, contents, ns);
    }
}

This is MyConfig:

public class MyConfig
{
    [XmlElement("Item")]
    public List<Item> Items { get; set; }

    public MyConfig()
    {
        Items = new List<Item>();
    }
}

public class Item : IXmlSerializable
{
    [XmlAttribute()]
    public string Attrib1 { get; set; }

    [XmlAttribute()]
    public string Attrib2 { get; set; }

    [XmlAttribute()]
    public string Attrib3 { get; set; }

    public Item(string attrib1, string attrib2, string attrib3)
    {
        Attrib1 = attrib1;
        Attrib2 = attrib2;
        Attrib3 = attrib3;
    }

    public XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        if (reader.MoveToContent() == XmlNodeType.Element)
        {
            Attrib1 = reader.GetAttribute("a1");
            Attrib2 = reader.GetAttribute("a2");
            Attrib3 = reader.GetAttribute("a3");
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString("a1", Attrib1);
        writer.WriteAttributeString("a2", Attrib2);
        writer.WriteAttributeString("a3", Attrib3);
    }
}

I then have the following test bed code for checking the serialization of the class:

string file = "somePath";

MyConfig myConfig = new MyConfig()
{
    Items = new List<Item>()
    {
        new Item("Attrib11", "Attrib21", "Attrib31"),
        new Item("Attrib12", "Attrib22", "Attrib32"),
    },
};

Save(file, myConfig);

MyConfig myConfig2 = Load<MyConfig>(file);

This fails with an OutOfMemory exception at Load, how can I fix this? Checking the file at somePath and it looks correct.

2
  • In your ReadXml() do you correctly consume the outer element? See Proper way to implement IXmlSerializable? and codeproject.com/Articles/43237/… Commented Oct 9, 2017 at 14:42
  • @dbc I have put all the relevant code in here so you tell me, this is my first time doing a class that uses IXmlSerializable so I'm not quite sure what you mean. I read all of the attributes in though if that's what you mean. Commented Oct 9, 2017 at 14:44

1 Answer 1

2

You need to tell the reader to advance to the next node after you've read the attributes:

public void ReadXml(XmlReader reader)
{
    if (reader.MoveToContent() == XmlNodeType.Element)
    {
        Attrib1 = reader.GetAttribute("a1");
        Attrib2 = reader.GetAttribute("a2");
        Attrib3 = reader.GetAttribute("a3");
    }
    // Go to the next node.
    reader.Read();
}

If you don't call reader.Read(), the reader reads the same node over and over again, and therefore the XmlSerializer will create an unlimited amount of Item instances until you finally get the OutOfMemoryException.

Sign up to request clarification or add additional context in comments.

3 Comments

@TheLethalCoder Most likely it would be the same as reader.MoveToNext() but XmlReader doesn't have such a method. All the reader.MoveToXXX() methods are just moving the reader within the current node but they don't advance the reader to the next node.
Not the best named method then in my opinion, it isn't too obvious what it actually does.
@TheLethalCoder I absolutely agree! All of these methods are available since .NET 1.1 without any significant changes. And there surely are a few more of those ancient parts in the .NET framework that don't make much sense if you look at them from a modern point of view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.