使用 IXmlSerializable 的自定义 class 因 OutOfMemoryException 而失败
Custom class with IXmlSerializable fails with OutOfMemoryException
我有以下 xml 文件:
<MyConfig>
<Item a1="Attrib11" a2="Attrib21" a3="Attrib31" />
<Item a1="Attrib12" a2="Attrib22" a3="Attrib32" />
</MyConfig>
我使用以下辅助方法加载它:
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);
}
}
这是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);
}
}
然后我有以下测试床代码用于检查 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);
这失败并在 Load
出现 OutOfMemory 异常,我该如何解决这个问题?在 somePath
检查文件,它看起来是正确的。
读取属性后需要告诉reader
前进到下一个节点:
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();
}
如果不调用reader.Read()
,reader
会一遍又一遍地读取同一个节点,因此XmlSerializer
会创建无限量的Item
实例,直到你最终得到 OutOfMemoryException
.
我有以下 xml 文件:
<MyConfig>
<Item a1="Attrib11" a2="Attrib21" a3="Attrib31" />
<Item a1="Attrib12" a2="Attrib22" a3="Attrib32" />
</MyConfig>
我使用以下辅助方法加载它:
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);
}
}
这是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);
}
}
然后我有以下测试床代码用于检查 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);
这失败并在 Load
出现 OutOfMemory 异常,我该如何解决这个问题?在 somePath
检查文件,它看起来是正确的。
读取属性后需要告诉reader
前进到下一个节点:
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();
}
如果不调用reader.Read()
,reader
会一遍又一遍地读取同一个节点,因此XmlSerializer
会创建无限量的Item
实例,直到你最终得到 OutOfMemoryException
.