如何将 TimeSpan 序列化为 XML
我正在尝试将 .NET TimeSpan
对象序列化为 XML,但它不起作用。 快速谷歌搜索后发现,虽然 TimeSpan
是可序列化的,但 XmlCustomFormatter
不提供将 TimeSpan
对象与 XML 相互转换的方法。
一种建议的方法是忽略 TimeSpan
进行序列化,而是序列化 TimeSpan.Ticks
的结果(并使用 new TimeSpan(ticks)
进行序列化)反序列化)。 一个例子如下:
[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 进行序列化?
I am trying to serialize a .NET TimeSpan
object to XML and it is not working. A quick google has suggested that while TimeSpan
is serializable, the XmlCustomFormatter
does not provide methods to convert TimeSpan
objects to and from XML.
One suggested approach was to ignore the TimeSpan
for serialization, and instead serialize the result of TimeSpan.Ticks
(and use new TimeSpan(ticks)
for deserialization). An example of this follows:
[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); }
}
}
While this appears to work in my brief testing - is this the best way to achieve this?
Is there a better way to serialize a TimeSpan to and from XML?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
这只是对问题中建议的方法的轻微修改,但是 此 Microsoft Connect 问题 建议使用如下属性进行序列化:
这会将 0:02:45 的 TimeSpan 序列化为:
或者,
DataContractSerializer
支持时间跨度。This is only a slight modification on the approach suggested in the question, but this Microsoft Connect issue recommends using a property for serialization like this:
This would serialize a TimeSpan of 0:02:45 as:
Alternatively, the
DataContractSerializer
supports TimeSpan.您已经发布的方式可能是最干净的。 如果您不喜欢额外的属性,您可以实现
IXmlSerialized
,但随后您必须执行所有操作,这在很大程度上违背了这一点。 我很乐意使用您发布的方法; 它(例如)高效(没有复杂的解析等)、文化独立、明确,并且时间戳类型的数字易于理解。顺便说一句,我经常补充:
这只是将其隐藏在 UI 和引用 dll 中,以避免混淆。
The way you've already posted is probably the cleanest. If you don't like the extra property, you could implement
IXmlSerializable
, but then you have to do everything, which largely defeats the point. I'd happily use the approach you've posted; it is (for example) efficient (no complex parsing etc), culture independent, unambiguous, and timestamp-type numbers are easily and commonly understood.As an aside, I often add:
This just hides it in the UI and in referencing dlls, to avoid confusion.
在某些情况下,可以为您的公共属性提供一个支持字段,即 TimeSpan,但公共属性以字符串形式公开。
例如:
如果属性值主要在包含类或继承类中使用并且从 xml 配置加载,则这是可以的。
如果您希望公共属性成为其他类的可用 TimeSpan 值,则其他建议的解决方案会更好。
Something that can work in some cases is to give your public property a backing field, which is a TimeSpan, but the public property is exposed as a string.
eg:
This is ok if the property value is used mostly w/in the containing class or inheriting classes and is loaded from xml configuration.
The other proposed solutions are better if you want the public property to be a usable TimeSpan value for other classes.
结合 颜色序列化 和 这个原始解决方案(本身就很棒)我得到了这个解决方案:
其中
XmlTimeSpan
类是这样的:Combining an answer from Color serialization and this original solution (which is great by itself) I got this solution:
where
XmlTimeSpan
class is like this:您可以围绕 TimeSpan 结构创建一个轻型包装器:
示例序列化结果:
You could create a light wrapper around the TimeSpan struct:
Sample serialized result:
更具可读性的选项是将其序列化为字符串并使用 TimeSpan.Parse 方法对其进行反序列化。 您可以执行与示例中相同的操作,但在 getter 中使用
TimeSpan.ToString()
并在 setter 中使用TimeSpan.Parse(value)
。A more readable option would be to serialize as a string and use the
TimeSpan.Parse
method to deserialize it. You could do the same as in your example but usingTimeSpan.ToString()
in the getter andTimeSpan.Parse(value)
in the setter.对于 .NET6 和 .NET7,TimeSpan 序列化可以开箱即用。 该格式是 XSD“duration”数据类型的格式。 因此“14:30”被序列化为
PT14H30M
对于 .NET Framework 4.8,可以使用以下开关激活此行为:
For .NET6 and .NET7, TimeSpan serialization works out of the box. The format is the format for XSD "duration" datatype. So "14:30" is serialized to
PT14H30M
For .NET Framework 4.8, this behavior can be activated with this switch:
我的解决方案版本。
编辑:假设它可以为空:
My version of the solution.
Edit: assuming it is nullable:
另一种选择是使用 SoapFormatter 类而不是 XmlSerializer 类对其进行序列化。
生成的 XML 文件看起来有点不同...一些带有“SOAP”前缀的标签等...但它可以做到。
以下是
SoapFormatter
将 20 小时 28 分钟的时间跨度序列化为:要使用 SOAPFormatter 类,需要添加对
System.Runtime.Serialization.Formatters.Soap
的引用并使用同名的命名空间。Another option would be to serialize it using the
SoapFormatter
class rather than theXmlSerializer
class.The resulting XML file looks a little different...some "SOAP"-prefixed tags, etc...but it can do it.
Here's what
SoapFormatter
serialized a timespan of 20 hours and 28 minutes serialized to:To use SOAPFormatter class, need to add reference to
System.Runtime.Serialization.Formatters.Soap
and use the namespace of the same name.时间跨度以秒数形式存储在 xml 中,但我希望它很容易采用。
手动序列化时间跨度(实现 IXmlSerialized):
有更全面的示例:
https://bitbucket.org/njkazakov/timespan-serialization
查看 Settings.cs。
使用 XmlElementAttribute 有一些棘手的代码。
Timespan stored in xml as number of seconds, but it is easy to adopt, I hope.
Timespan serialized manually (implementing IXmlSerializable):
There is more comprehensive example:
https://bitbucket.org/njkazakov/timespan-serialization
Look at Settings.cs.
And there is some tricky code to use XmlElementAttribute.
如果您不需要任何解决方法,请使用 System.Runtime.Serialization.dll 中的 DataContractSerializer 类。
If you do not want any workarounds, use the DataContractSerializer class from System.Runtime.Serialization.dll.
对于数据契约序列化,我使用以下内容。
For data contract serialization I use the following.
尝试这个 :
Try this :