.NET Как сериализовать TimeSpan для XML (не тот же вопрос!)
Мой вопрос является продолжением Как сериализовать TimeSpan для XML
У меня есть много объектов DTO, которые передают экземпляры TimeSpan
. Использование взлома, описанного в оригинальной публикации, но требует от меня повторить ту же самую часть кода в каждом DTO для каждого свойства TimeSpan
.
Итак, я пришел со следующим классом-оболочкой, который отлично сериализуется 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); }
}
}
Проблема заключается в том, что создаваемый XML выглядит так:
<Duration>
<Value>20000</Value>
</Duration>
вместо естественного
<Duration>20000</Duration>
Мой вопрос: могу ли я "съесть торт и сделать его целым"? Смысл, наслаждайтесь описанным взломом, не загромождая все DTO с тем же повторяющимся кодом и все же обладаете естественным образом выглядящим XML?
Спасибо.
Ответы
Ответ 1
Измените [XmlElement("Value")]
на [XmlText]
. Затем, если вы сериализуете что-то вроде этого:
[Serializable]
public class TestEntity
{
public string Name { get; set; }
public TimeSpanWrapper Time { get; set; }
}
Вы получите XML следующим образом:
<TestEntity>
<Name>Hello</Name>
<Time>3723000</Time>
</TestEntity>
Ответ 2
Вам нужно будет реализовать 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 };
}
}