我试图将. net TimeSpan对象序列化为XML,但它不起作用。快速谷歌表明,虽然TimeSpan是可序列化的,但XmlCustomFormatter没有提供将TimeSpan对象转换为XML或从XML转换的方法。
一种建议的方法是忽略TimeSpan进行序列化,而是序列化TimeSpan的结果。刻度(并使用新的TimeSpan(刻度)进行反序列化)。下面是一个例子:
[Serializable]
public class MyClass
{
// Local Variable
private TimeSpan m_TimeSinceLastEvent;
// Public Property - XmlIgnore as it doesn't serialize anyway
[XmlIgnore]
public TimeSpan TimeSinceLastEvent
{
get { return m_TimeSinceLastEvent; }
set { m_TimeSinceLastEvent = value; }
}
// Pretend property for serialization
[XmlElement("TimeSinceLastEvent")]
public long TimeSinceLastEventTicks
{
get { return m_TimeSinceLastEvent.Ticks; }
set { m_TimeSinceLastEvent = new TimeSpan(value); }
}
}
虽然这在我的简短测试中似乎是有效的,但这是实现这一目标的最佳方式吗?
是否有更好的方法将TimeSpan与XML进行序列化?
Timespan以秒数的形式存储在xml中,但是我希望它很容易采用。
手动序列化的时间跨度(实现IXmlSerializable):
public class Settings : IXmlSerializable
{
[XmlElement("IntervalInSeconds")]
public TimeSpan Interval;
public XmlSchema GetSchema()
{
return null;
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("IntervalInSeconds", ((int)Interval.TotalSeconds).ToString());
}
public void ReadXml(XmlReader reader)
{
string element = null;
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
element = reader.Name;
else if (reader.NodeType == XmlNodeType.Text)
{
if (element == "IntervalInSeconds")
Interval = TimeSpan.FromSeconds(double.Parse(reader.Value.Replace(',', '.'), CultureInfo.InvariantCulture));
}
}
}
}
还有一个更全面的例子:
https://bitbucket.org/njkazakov/timespan-serialization
查看Settings.cs。
使用XmlElementAttribute需要一些复杂的代码。
这只是对问题中建议的方法进行了轻微的修改,但是这个Microsoft Connect问题建议使用这样的属性进行序列化:
[XmlIgnore]
public TimeSpan TimeSinceLastEvent
{
get { return m_TimeSinceLastEvent; }
set { m_TimeSinceLastEvent = value; }
}
// XmlSerializer does not support TimeSpan, so use this property for
// serialization instead.
[Browsable(false)]
[XmlElement(DataType="duration", ElementName="TimeSinceLastEvent")]
public string TimeSinceLastEventString
{
get
{
return XmlConvert.ToString(TimeSinceLastEvent);
}
set
{
TimeSinceLastEvent = string.IsNullOrEmpty(value) ?
TimeSpan.Zero : XmlConvert.ToTimeSpan(value);
}
}
这将序列化0:02:45的TimeSpan为:
<TimeSinceLastEvent>PT2M45S</TimeSinceLastEvent>
或者,DataContractSerializer支持TimeSpan。