You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现IXmlSerializable的struct调用Deserialize()时抛出InvalidProgramException

问题原因与解决方案

核心问题分析

  1. 值类型实现IXmlSerializable的CLR限制:TestUnit是struct(值类型),XmlSerializer在为值类型生成序列化代理代码时存在兼容性问题,直接触发InvalidProgramException,这是异常的根本原因,同时导致ReadXml无法被正常调用。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 12:42:41