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

Native AOT编译下XmlSerializer反序列化报错排查及疑问:为何默认XmlSerializer反序列化需要动态代码生成?

Native AOT编译下XmlSerializer反序列化报错排查及疑问:为何默认XmlSerializer反序列化需要动态代码生成?

最近我在给公司做一个解析WCF服务MEX端点数据的工具,功能本身跑起来都顺顺当当的,直到产品那边提了个常规需求:把.NET项目编译成Native AOT——理由无非是不用装.NET运行时,还能提升性能。结果刚到测试环节就炸了,报了个让人一头雾水的错误:

System.InvalidOperationException
  HResult=0x80131509
  Message = There is an error in XML document (0, 0).
  Source = System.Private.Xml
  Stack trace:
   in System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   in System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader)
   in System.Web.Services.Description.ServiceDescription.Read(XmlReader reader, Boolean validate)
   in System.Web.Services.Description.ServiceDescription.Read(Stream stream, Boolean validate)
   in DocSynth.Remote.WCF.Services.WSDLParser.ReadWSDLFiles(IEnumerable`1 filePaths)
   in DocSynth.Remote.WCF.Services.WCFMEXMetadataProvider.ParseWCFFiles(WCFFilesPreparationResult files)

  Initial Stack trace: 
    System.ArgumentNullException.Throw(string)
    System.ArgumentNullException.ThrowIfNull(object, string)
    System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(System.Type, System.Xml.Serialization.XmlRootAttribute, string)
    System.Xml.Serialization.XmlSerializer.GetMapping()
    System.Xml.Serialization.XmlSerializer.Deserialize(System.Xml.XmlReader, string, System.Xml.Serialization.XmlDeserializationEvents)

Internal Exception 1:
ArgumentNullException: Value cannot be null. Arg_ParamName_Name

什么情况?XML文档(0,0)出错?我百分百确定WSDL文件没问题啊——这是从MEX端点直接拿的,我手动检查过,完全没有XML语法问题。

我开始一步步死磕这个问题:

  • 一开始怀疑是流的位置问题,比如XMLTextReader读取流时会自动偏移4096字节,试着把流的Position设回0,没用。
  • 接着逐行调试代码,发现调用ServiceDescription.Read(fs)时,走的是XmlSerializer的反射反序列化分支,而不是自定义的反序列化逻辑。
  • 追进源码看,发现GetMapping方法里的_rootType是空的,直接触发了空指针异常。
  • 再看ServiceDescription里的自定义Serializer:它是XmlSerializer的子类,重写了CreateReader、CreateWriter这些核心方法,本身根本不需要_rootType——因为自定义读写器会处理所有解析逻辑。那为什么会走到反射分支?
  • 查ShouldUseReflectionBasedSerialization方法的实现,发现当_mapping为空(这个自定义Serializer确实没初始化mapping),就只看Mode是不是ReflectionOnly。
  • 最后看到Mode的核心逻辑:
    internal static SerializationMode Mode
    {
        get => RuntimeFeature.IsDynamicCodeSupported ? s_mode : SerializationMode.ReflectionOnly;
        set => s_mode = value;
    }
    
    瞬间恍然大悟!我两周前开了项目属性里的「Enable native AOT publication」开关,Native AOT环境下RuntimeFeature.IsDynamicCodeSupported必然是false,所以Mode直接被设为了ReflectionOnly。而这个自定义Serializer完全没做反射反序列化的适配,直接就空指针炸了。

最后只能给产品反馈:要是想用Native AOT编译,得自己写一套WSDL解析逻辑,现成的ServiceDescription用不了了。

不过我还是满肚子疑惑:为什么XmlSerializer在Native AOT编译的程序里,反序列化需要依赖动态代码生成?按说Native AOT是把所有类型都提前编译打包进可执行文件了,反射根本不应该用来动态创建或修改类型啊?


备注:内容来源于stack exchange,提问作者ZecosMAX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 10:08:01