【问题标题】:Deserialize custom XML datatype in C#在 C# 中反序列化自定义 XML 数据类型
【发布时间】:2011-01-17 22:12:36
【问题描述】:

我有一个我无法控制的 xml 文档,其中包含具有自定义数据类型的元素

<foo>
   <time type="epoch_seconds">1295027809.26896</time>
</foo>

我想要一个可以自动转换为Epoch秒的类:

[Serializable]
public class Foo
{
      public Foo()
      {
      }

      public EpochTime Time { get; set; }
}

有没有办法定义一个EpochTime 类,以便XML 序列化程序在使用type="epoch_time" 查找XML 时知道使用它?如果是这样,我该如何设置 WriteXmlReadXml 来做到这一点?

【问题讨论】:

  • [Serializable]不影响xml序列化)

标签: c# xml serialization types


【解决方案1】:

通常的方法是简单地用一个行为如你所料的属性来填充它:

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 */ }
    }
}

另外,你需要:

[XmlElement("time")]
public EpochTime Time { get; set; }

这是您的 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; }
}

【讨论】:

    【解决方案2】:

    你真的需要实现ISerializable吗?以下可能适用于您的方案:

    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);
        }
    }
    

    还要注意[Serializable]XmlSerializer 没有影响。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 1970-01-01
      • 2010-12-20
      • 1970-01-01
      • 2011-11-03
      相关资源
      最近更新 更多