使用Native AOT发布后XmlSerializer反序列化XML至C#对象异常
Native AOT发布后XmlSerializer反序列化报错“XML文档(0, 0)中有错误”的解决办法
问题根源
Native AOT是静态提前编译模式,发布阶段会把所有代码编译为机器码,不允许运行时动态生成新代码。而传统XmlSerializer默认会在首次序列化/反序列化时动态生成对应的程序集,这在AOT环境下直接失效,最终表现为看似XML格式错误的异常(实际是底层代码生成失败的间接报错)。
解决方案
方案1:预先生成XmlSerializer专用程序集
使用.NET SDK工具提前生成实体类的序列化程序集,让AOT编译时能直接包含这些代码,避免运行时动态生成。
手动生成方式
打开命令行进入项目输出目录,执行:
sgen.exe /assembly:YourProject.dll /type:YourNamespace.YourTargetEntity
YourProject.dll:替换为你的项目编译输出程序集名称YourNamespace.YourTargetEntity:替换为需要序列化的实体类完整命名空间+类名
生成的YourProject.XmlSerializers.dll会和主程序集放在一起,发布时务必包含该文件。
自动生成方式
在项目文件(.csproj)中添加配置,编译时自动生成序列化程序集:
<PropertyGroup> <!-- .NET Framework直接用这个配置 --> <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies> </PropertyGroup> <!-- .NET Core/.NET 5+需要先安装Microsoft.XmlSerializer.Generator NuGet包,再添加上述配置 -->
方案2:改用手动XML解析或兼容AOT的序列化方案
如果XML结构不复杂,可以直接用XmlReader手动解析,完全规避动态代码生成问题:
using System.Xml; using System.IO; public static YourTargetEntity DeserializeXml(string xmlContent) { var entity = new YourTargetEntity(); using var reader = XmlReader.Create(new StringReader(xmlContent)); // 读取指定节点内容,示例: reader.ReadToFollowing(nameof(YourTargetEntity.Id)); entity.Id = reader.ReadElementContentAsInt(); reader.ReadToFollowing(nameof(YourTargetEntity.Name)); entity.Name = reader.ReadElementContentAsString(); return entity; }
也可以选择支持AOT的第三方XML序列化库(需确认库的AOT兼容性),或者将XML转换为JSON后使用System.Text.Json处理(适合简单结构)。
方案3:启用.NET 7+的XmlSerializer AOT原生支持
从.NET 7开始,XmlSerializer提供了有限的AOT支持,通过配置告诉编译器提前为目标类型生成序列化代码:
- 在项目文件中添加:
<ItemGroup> <TrimmerRootDescriptor Include="XmlAotConfig.xml" /> </ItemGroup>
- 创建
XmlAotConfig.xml配置文件,指定需要序列化的类型:
<linker> <assembly fullname="YourProject"> <type fullname="YourNamespace.YourTargetEntity" serialize="true" /> <!-- 可添加更多需要序列化的类型 --> </assembly> </linker>
完成配置后,执行Native AOT发布命令即可:
dotnet publish -c Release -r win-x64 /p:PublishAot=true
(替换win-x64为你的目标运行时,比如linux-x64、osx-x64等)
内容的提问来源于stack exchange,提问作者Adham Lachinov
相关产品推荐
相关产品推荐

