当前位置:  开发笔记 > 编程语言 > 正文

如何将TimeSpan序列化为XML

如何解决《如何将TimeSpan序列化为XML》经验,为你挑选了6个好方法。

我试图将.NET TimeSpan对象序列化为XML,但它无法正常工作.一个快速谷歌建议,虽然TimeSpan是可序列化的,但XmlCustomFormatter它不提供将TimeSpan对象转换为XML或从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?



1> Rory MacLeod..:

这只是对问题中建议的方法稍作修改,但此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序列化为:

PT2M45S

或者,DataContractSerializer支持TimeSpan.


+1 for XmlConvert.ToTimeSpan().它处理时间跨度的ISO标准持续时间语法,如PT2H15M,请参阅http://en.wikipedia.org/wiki/ISO_8601#Durations
如果我错了,请纠正我,但是时间跨度为"PT2M45S"的时间是00:02:45,而不是2:45:00.

2> Marc Gravell..:

你已经发布的方式可能是最干净的.如果你不喜欢额外的财产,你可以实施IXmlSerializable,但是你必须做所有事情,这在很大程度上违背了这一点.我很乐意使用你发布的方法; 它(例如)有效(没有复杂的解析等),文化独立,明确,并且时间戳类型的数字易于和通常被理解.

顺便说一句,我经常补充说:

[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

这只是隐藏在UI和引用dll中,以避免混淆.


如果在包装System.TimeSpan的结构上实现接口,而不是在MyClass上实现它,那么执行__everything__并不是那么糟糕.然后,您只需要更改MyClass.TimeSinceLastEvent属性的类型

3> Wes..:

在某些情况下可以使用的是为您的公共属性提供一个支持字段,即TimeSpan,但公共属性是作为字符串公开的.

例如:

protected TimeSpan myTimeout;
public string MyTimeout 
{ 
    get { return myTimeout.ToString(); } 
    set { myTimeout = TimeSpan.Parse(value); }
}

如果属性值主要用于包含类或继承类并且从xml配置加载,则可以.

如果您希望公共属性成为其他类的可用TimeSpan值,则其他建议的解决方案会更好.



4> Mikhail..:

结合Color序列化和这个原始解决方案(这本身很棒)的答案我得到了这个解决方案:

[XmlElement(Type = typeof(XmlTimeSpan))]
public TimeSpan TimeSinceLastEvent { get; set; }

其中XmlTimeSpan类是这样的:

public class XmlTimeSpan
{
    private const long TICKS_PER_MS = TimeSpan.TicksPerMillisecond;

    private TimeSpan m_value = TimeSpan.Zero;

    public XmlTimeSpan() { }
    public XmlTimeSpan(TimeSpan source) { m_value = source; }

    public static implicit operator TimeSpan?(XmlTimeSpan o)
    {
        return o == null ? default(TimeSpan?) : o.m_value;
    }

    public static implicit operator XmlTimeSpan(TimeSpan? o)
    {
        return o == null ? null : new XmlTimeSpan(o.Value);
    }

    public static implicit operator TimeSpan(XmlTimeSpan o)
    {
        return o == null ? default(TimeSpan) : o.m_value;
    }

    public static implicit operator XmlTimeSpan(TimeSpan o)
    {
        return o == default(TimeSpan) ? null : new XmlTimeSpan(o);
    }

    [XmlText]
    public long Default
    {
        get { return m_value.Ticks / TICKS_PER_MS; }
        set { m_value = new TimeSpan(value * TICKS_PER_MS); }
    }
}



5> phoog..:

您可以在TimeSpan结构周围创建一个光包装器:

namespace My.XmlSerialization
{
    public struct TimeSpan : IXmlSerializable
    {
        private System.TimeSpan _value;

        public static implicit operator TimeSpan(System.TimeSpan value)
        {
            return new TimeSpan { _value = value };
        }

        public static implicit operator System.TimeSpan(TimeSpan value)
        {
            return value._value;
        }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            _value = System.TimeSpan.Parse(reader.ReadContentAsString());
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteValue(_value.ToString());
        }
    }
}

样本序列化结果:


  2010-12-06T08:45:12.5
  2.08:29:35.2500000



6> Rune Grimsta..:

更可读的选项是序列化为字符串并使用该TimeSpan.Parse方法对其进行反序列化.您可以在示例中执行相同操作,但TimeSpan.ToString()在getter和TimeSpan.Parse(value)setter中使用.

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有