[英]Deserialize custom XML datatype in C#
I have an xml document that I don't control that has an element with a custom datatype 我有一个我无法控制的xml文档,它有一个带有自定义数据类型的元素
<foo>
<time type="epoch_seconds">1295027809.26896</time>
</foo>
I would like to have a class that could automatically convert to Epoch seconds: 我想有一个类可以自动转换为Epoch秒:
[Serializable]
public class Foo
{
public Foo()
{
}
public EpochTime Time { get; set; }
}
Is there a way to define an EpochTime
class so that the XML serializer knows to use it when finding XML with type="epoch_time"
? 有没有办法定义
EpochTime
类,以便XML序列化器在查找type="epoch_time"
XML时知道使用它? And if so, how do I set up the WriteXml
and ReadXml
to do it? 如果是这样,我如何设置
WriteXml
和ReadXml
来做到这一点?
The normal way is to simply shim it with a property that behaves as you expect: 通常的方法是使用行为与您期望的属性简单地填充它:
public class EpochTime {
public enum TimeType {
[XmlEnum("epoch_seconds")] Seconds
}
[XmlAttribute("type")] public TimeType Type {get;set;}
[XmlText] public string Text {get;set;}
[XmlIgnore] public DateTime Value {
get { /* your parse here */ }
set { /* your format here */ }
}
}
also, you would need: 另外,你需要:
[XmlElement("time")]
public EpochTime Time { get; set; }
Here's a complete example with your xml: 这是xml的完整示例:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
static class Program
{
static void Main()
{
Foo foo;
var ser = new XmlSerializer(typeof(Foo));
using (var reader = XmlReader.Create(new StringReader(@"<foo>
<time type=""epoch_seconds"">1295027809.26896</time>
</foo>")))
{
foo = (Foo)ser.Deserialize(reader);
}
}
}
public class EpochTime
{
public enum TimeType
{
[XmlEnum("epoch_seconds")]
Seconds
}
[XmlAttribute("type")]
public TimeType Type { get; set; }
[XmlText]
public string Text { get; set; }
private static readonly DateTime Epoch = new DateTime(1970, 1, 1);
[XmlIgnore] public DateTime Value
{
get
{
switch (Type)
{
case TimeType.Seconds:
return Epoch + TimeSpan.FromSeconds(double.Parse(Text));
default:
throw new NotSupportedException();
}
}
set {
switch (Type)
{
case TimeType.Seconds:
Text = (value - Epoch).TotalSeconds.ToString();
break;
default:
throw new NotSupportedException();
}
}
}
}
[XmlRoot("foo")]
public class Foo
{
public Foo()
{
}
[XmlElement("time")]
public EpochTime Time { get; set; }
}
Do you really need to implement ISerializable ? 你真的需要实现ISerializable吗? The following might work in your scenario:
以下可能适用于您的方案:
public class EpochTime
{
[XmlText]
public double Data { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
}
public class Foo
{
public EpochTime Time { get; set; }
}
class Program
{
public static void Main()
{
var foo = new Foo
{
Time = new EpochTime
{
Data = 1295027809.26896,
Type = "epoch_seconds"
}
};
var serializer = new XmlSerializer(foo.GetType());
serializer.Serialize(Console.Out, foo);
}
}
Also notice that [Serializable]
has no effect on XmlSerializer . 另请注意,
[Serializable]
对XmlSerializer没有影响。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.