如何在不修改自动生成类时自定义XmlSerializer日期序列化格式
自定义XmlSerializer序列化第三方自动生成类的日期格式
问题背景
有从第三方XSD自动生成的partial实体类:
public partial class MyRegistry { public DateTime MyDateTime { get; set; } }
使用默认XmlSerializer序列化时,日期输出为ISO标准格式:
var myRegistry = new MyRegistry() { MyDateTime = DateTime.Now }; var serializer = new XmlSerializer(typeof(MyRegistry)); using (var stringWriter = new StringWriter()) { serializer.Serialize(stringWriter, myRegistry); Console.WriteLine(stringWriter.ToString()); }
输出结果:
<?xml version="1.0" encoding="utf-16"?> <MyRegistry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <MyDateTime>2024-04-07T12:05:21.9739342+02:00</MyDateTime> </MyRegistry>
需要将日期格式改为*dd/MM/yyyy hh:mm*,但直接修改自动生成的类会在XSD更新时丢失,因此需寻找无需修改原始类/XSD的解决方案。
解决方案
方案1:Partial类扩展 + XmlAttributeOverrides动态配置
利用C# partial类的特性,在独立文件中扩展类并添加格式化属性,再通过XmlAttributeOverrides告诉序列化器忽略原日期属性:
- 创建独立文件扩展partial类:
// 此文件不会被XSD生成工具覆盖 public partial class MyRegistry { [XmlElement("MyDateTime")] public string MyDateTimeFormatted { get => MyDateTime.ToString("dd/MM/yyyy hh:mm"); set => MyDateTime = DateTime.ParseExact(value, "dd/MM/yyyy hh:mm", null); } }
- 序列化时应用属性覆盖配置:
var overrides = new XmlAttributeOverrides(); // 标记原MyDateTime属性为XmlIgnore var ignoreAttrs = new XmlAttributes { XmlIgnore = true }; overrides.Add(typeof(MyRegistry), nameof(MyRegistry.MyDateTime), ignoreAttrs); // 使用配置好的overrides创建序列化器 var serializer = new XmlSerializer(typeof(MyRegistry), overrides); var myRegistry = new MyRegistry() { MyDateTime = DateTime.Now }; using (var stringWriter = new StringWriter()) { serializer.Serialize(stringWriter, myRegistry); Console.WriteLine(stringWriter.ToString()); }
方案2:自定义XmlTextWriter处理日期格式
通过自定义XmlTextWriter,在写入XML时针对性替换指定节点的日期格式:
- 实现自定义XmlWriter:
public class CustomDateXmlWriter : XmlTextWriter { private string _currentElement; public CustomDateXmlWriter(TextWriter writer) : base(writer) { } public override void WriteStartElement(string prefix, string localName, string ns) { _currentElement = localName; base.WriteStartElement(prefix, localName, ns); } public override void WriteString(string text) { // 仅处理MyDateTime节点的日期格式 if (_currentElement == "MyDateTime" && DateTime.TryParse(text, out var date)) { base.WriteString(date.ToString("dd/MM/yyyy hh:mm")); } else { base.WriteString(text); } } }
- 序列化时使用自定义Writer:
var myRegistry = new MyRegistry() { MyDateTime = DateTime.Now }; var serializer = new XmlSerializer(typeof(MyRegistry)); using (var stringWriter = new StringWriter()) using (var xmlWriter = new CustomDateXmlWriter(stringWriter)) { serializer.Serialize(xmlWriter, myRegistry); Console.WriteLine(stringWriter.ToString()); }
内容的提问来源于stack exchange,提问作者Art
相关产品推荐
相关产品推荐

