2011-01-17 21 views
5

que tiene un documento XML que no control que tiene un elemento con un tipo de datos personalizadaDeserialize tipo de datos XML personalizado en C#

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

me gustaría tener una clase que podría convertir automáticamente a Epoch segundos:

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

     public EpochTime Time { get; set; } 
} 

¿hay una manera de definir una clase EpochTime para que el serializador XML sabe usarlo cuando la búsqueda de XML con type="epoch_time"? Y si es así, ¿cómo configuro el WriteXml y el ReadXml para hacerlo?

+0

('[Serializable]' no lo hace afectar la serialización xml) –

Respuesta

4

La manera normal es simplemente calce con una propiedad que se comporta como se esperaba:

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

también, lo que se necesita:

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

Aquí está un ejemplo completo con su 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; } 
} 
0

¿Realmente necesita implementar ISerializable? El siguiente podría funcionar en su escenario:

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

Observe también que [Serializable] tiene ningún efecto sobre XmlSerializer.

Cuestiones relacionadas