实现IXmlSerializable的struct调用Deserialize()时抛出InvalidProgramException
问题原因与解决方案
核心问题分析
- 值类型实现
IXmlSerializable的CLR限制:TestUnit是struct(值类型),XmlSerializer在为值类型生成序列化代理代码时存在兼容性问题,直接触发InvalidProgramException,这是异常的根本原因,同时导致ReadXml无法被正常调用。 - XML读写逻辑不符合XmlSerializer约定:
WriteXml中额外嵌套了<TestUnit>元素,生成的XML结构会变成<TestUnit><TestUnit Value="..." /></TestUnit>,层级结构错误。ReadXml中调用reader.ReadStartElement("TestUnit")时,reader已经定位到目标元素的起始位置,重复调用会导致读取位置偏移,无法正确获取属性。
修复步骤
1. 将struct改为class
把TestUnit从值类型改为引用类型,规避XmlSerializer对值类型IXmlSerializable的代理生成问题:
public class TestUnit : IXmlSerializable
2. 修正WriteXml实现
移除额外的<TestUnit>元素写入,直接在当前元素上添加属性:
public void WriteXml(XmlWriter writer) { writer.WriteAttributeString("Value", $"{Z} {C.X} {C.Y}"); }
3. 修正ReadXml实现
去掉多余的ReadStartElement调用,直接读取属性,最后调用ReadEndElement完成元素读取:
public void ReadXml(XmlReader reader) { var vals = reader.GetAttribute("Value").Split(); Z = int.Parse(vals[0]); C = new Point(int.Parse(vals[1]), int.Parse(vals[2])); reader.ReadEndElement(); }
4. 优化资源释放
确保读取文件流时也用using语句,避免资源泄漏:
TestUnit speed = new(); XmlSerializer serializer = new(typeof(TestUnit)); using (FileStream fileStream = File.OpenWrite("foo.txt")) serializer.Serialize(fileStream, speed); using (FileStream stream = File.OpenRead("foo.txt")) { TestUnit? sunit = serializer.Deserialize(stream) as TestUnit?; }
验证效果
修复后生成的XML结构为:
<TestUnit Value="0 0 0" />
反序列化时能正确读取属性值,不再抛出异常,ReadXml方法也能正常执行。
内容的提问来源于stack exchange,提问作者Doshorte Dovencio
相关产品推荐
相关产品推荐

