重写XmlSerializer中的日期时间分析,而不更改生成的代码
本文关键字:代码 XmlSerializer 日期 时间 重写 | 更新日期: 2023-09-27 18:21:41
我正在访问第三方API并检索一些XML。我还能够访问它的xsd,并使用xsd生成对象以使用XmlSerializer进行反序列化。
XML包含这样的日期:
<modified>2014-08-19T06:39:13.269-0400</modified>
生成的代码如下所示:
[System.Xml.Serialization.XmlElementAttribute(DataType="time")]
public System.DateTime modified {
get {
return this.modifiedField;
}
set {
this.modifiedField = value;
}
}
不幸的是,这会在尝试反序列化时导致错误。
我可以通过用XmlIgnore属性标记它并将这样的代码添加到分部类中来解决这个问题:
[XmlElement("modified")]
public string modifiedAsString
{
get { return this.modified.ToString(); }
set { this.modified = System.DateTime.Parse(value); }
}
然而,忽略部分是对生成的类的更改,我必须进行数百次这样的更改才能考虑到所有的日期时间。
我尝试了MetadataType这件事来从外部将属性应用到它,但不幸的是XmlSerializer没有接受。
有人建议我如何在不更改生成的代码或输入XML(这超出了我的控制范围)的情况下解析它吗?
如果您愿意将System.DateTime
更改为具有到System.DateTime
的隐式运算符的自定义包装类,则这是可能的。尽管我怀疑这可能比被忽略的helper属性更具破坏性。
您可以创建一个自定义类型来包装底层DateTime
,并执行必要的to/from解析。此外,您可以利用XmlTextAttribute
来控制输出以匹配<modified>2014-08-19T06:39:13.269-0400</modified>
模式:
public struct CustomDateTime
{
private DateTime UnderlyingDateTime;
[XmlText]
public string CustomFormat
{
get { return UnderlyingDateTime.ToString(); }
set { UnderlyingDateTime = System.DateTime.Parse(value); }
}
public static implicit operator DateTime(CustomDateTime custom)
{
return custom.UnderlyingDateTime;
}
public static implicit operator CustomDateTime(DateTime datetime)
{
return new CustomDateTime { UnderlyingDateTime = datetime };
}
}
这是一个包含Modified
属性的类(您没有提到名称,所以我只将其称为Foo
):
public class Foo
{
public CustomDateTime Modified { get; set; }
}
隐式运算符允许您在大多数情况下直接读取/写入DateTime
值:
Foo f = new Foo();
f.Modified = DateTime.Parse("2014-08-19T06:39:13.269-0400");
它支持您的标准火炬XmlSerializer
系列化:
XmlSerializer serializer = new XmlSerializer(typeof(Foo));
var textwriter = new StringWriter();
serializer.Serialize(textwriter, f);
string xml = textwriter.ToString();
Console.WriteLine(xml);
得到的XML(我已经去掉了一些通常会在根节点中的包装垃圾)是:
<Foo>
<Modified>2014-08-19 6:39:13 AM</Modified>
</Foo>
反序列化上面的XML:
Foo deserialized = (Foo)serializer.Deserialize(new StringReader(xml));
DateTime datetime = deserialized.Modified;
Console.WriteLine(datetime);
DateTime
输出的结果:2014-08-19 6:39:13 AM
现在,这与XML内容并不完全匹配,也就是说,它显示的是"2014-08-19 6:39:13 AM",而不是"2014-08-19T06:39:13.269-0400",但这只是因为我逐字逐句地跟踪您对get/set
属性使用DateTime.ToString()
和DateTime.Parse
的情况
然而,它会很好地读取XML内容,也就是说,如果传入的XML是:
<Foo>
<Modified>2014-08-19T06:39:13.269-0400</Modified>
</Foo>
它仍然以相同的方式读取它(本质上它将调用System.DateTime.Parse("2014-08-19T06:39:13.269-0400")
)。
编辑:只是澄清一下,你必须做出的突破性改变是将你原来的Foo
类从这个改为:
public class Foo
{
public DateTime Modified { get; set; }
}
对此:
public class Foo
{
public CustomDateTime Modified { get; set; }
}
我不确定在这种用法中是否正确模拟了[System.Xml.Serialization.XmlElementAttribute(DataType="time")]
属性的行为,但如果没有,您很容易就必须灵活地在CustomDateTime.CustomFormat
属性getter和setter中实现任何解析。