简体   繁体   English

.NET如何将TimeSpan序列化为XML(不是同一个问题!)

[英].NET How to serialize a TimeSpan to XML (not the same question!)

My question is a continuation of How to serialize a TimeSpan to XML 我的问题是如何将TimeSpan序列化为XML的延续

I have many DTO objects which pass TimeSpan instances around. 我有许多DTO对象传递TimeSpan实例。 Using the hack described in the original post works, but it requires me to repeat the same bulk of code in each and every DTO for each and every TimeSpan property. 使用原始帖子中描述的hack有效,但它要求我在每个DTO中为每个TimeSpan属性重复相同的代码。

So, I came with the following wrapper class, which is XML serializable just fine: 所以,我带来了以下包装类,它是XML可序列化的就好了:

#if !SILVERLIGHT
[Serializable]
#endif
[DataContract]
public class TimeSpanWrapper
{
  [DataMember(Order = 1)]
  [XmlIgnore]
  public TimeSpan Value { get; set; }

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

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

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

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

  [JsonIgnore]
  [XmlElement("Value")]
  [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
  public long ValueMilliSeconds
  {
    get { return Value.Ticks / 10000; }
    set { Value = new TimeSpan(value * 10000); }
  }
}

The problem is that the XML it produces looks like so: 问题是它产生的XML看起来像这样:

<Duration>
  <Value>20000</Value>
</Duration>

instead of the natural 而不是自然

<Duration>20000</Duration>

My question is can I both "eat the cake and have it whole"? 我的问题是,我可以“吃蛋糕,吃完全”吗? Meaning, enjoy the described hack without cluttering all the DTOs with the same repetitive code and yet have a natural looking XML? 意思是,享受所描述的hack而不会使用相同的重复代码混乱所有DTO并且具有自然的外观XML?

Thanks. 谢谢。

Change [XmlElement("Value")] to [XmlText] . [XmlElement("Value")]更改为[XmlText] Then, if you serialize something like this: 然后,如果你序列化这样的事情:

[Serializable]
public class TestEntity
{
    public string Name { get; set; }
    public TimeSpanWrapper Time { get; set; }
}

You will get XML like this: 你会得到这样的XML:

<TestEntity>
    <Name>Hello</Name>
    <Time>3723000</Time>
</TestEntity>

You will need to implement IXmlSerializable: 您需要实现IXmlSerializable:

[Serializable,XmlSchemaProvider("TimeSpanSchema")]
public class TimeSpanWrapper : IXmlSerializable
{
    private TimeSpan _value;

    public TimeSpanWrapper()
    {
        _value = TimeSpan.Zero;
    }

    public TimeSpanWrapper(TimeSpan value)
    {
        _value = value;
    }

    public XmlSchema GetSchema() {
        return null;
    }

    public void ReadXml(XmlReader reader) {
        _value = XmlConvert.ToTimeSpan(reader.ReadElementContentAsString());
    }

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

    public static XmlQualifiedName TimeSpanSchema(XmlSchemaSet xs)
    {
        return new XmlQualifiedName("duration", "http://www.w3.org/2001/XMLSchema");
    }

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

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM