2011-05-11 10 views
10

Supongamos que tenemos una clase que puede ser serializada/deserializada por XmlSerializer. Sería así:Conversor de propiedades XmlSerializer

[XmlRoot("ObjectSummary")] 
public class Summary 
{ 
    public string Name {get;set;} 
    public string IsValid {get;set;} 
} 

Tenemos un xml que será así:

<ObjectSummary> 
    <Name>some name</Name> 
    <IsValid>Y</IsValid> 
<ObjectSummary> 

El uso de la propiedad booleana IsValid en lugar de propiedad de cadena es mucho mejor decisión, pero en este caso necesitamos para agregar alguna lógica adicional para convertir datos de cadena a bool.

La forma simple y directa de resolver este problema es usar propiedad adicional y poner alguna lógica de conversión en el captador de IsValid.

¿Alguien puede sugerir una mejor decisión? Para usar un convertidor de tipo en atributos de alguna manera o algo similar?

+1

Su pregunta no está clara para mí. ¿Por qué no estás usando un bool? – bnieland

+2

OP quiere que IsValid sea booleano pero muestra Y y N en lugar de falso y verdadero. – Aliostad

+0

Esta es una buena pregunta sobre bool :) Creo que es una decisión muy lógica usar una propiedad bool, pero desafortunadamente el xml descrito anteriormente proviene del sistema externo, por lo que no tengo la capacidad de cambiar nada. Muy triste, ¿verdad? :) – madcyree

Respuesta

10

Tratar el nodo como un tipo personalizado:

[XmlRoot("ObjectSummary")] 
public class Summary 
{ 
    public string Name {get;set;} 
    public BoolYN IsValid {get;set;} 
} 

luego implementar IXmlSerializable del tipo de encargo:

public class BoolYN : IXmlSerializable 
{ 
    public bool Value { get; set } 

    #region IXmlSerializable members 

    public System.Xml.Schema.XmlSchema GetSchema() { 
     return null; 
    } 

    public void ReadXml(System.Xml.XmlReader reader) { 
     string str = reader.ReadString(); 
     reader.ReadEndElement(); 

     switch (str) { 
      case "Y": 
       this.Value = true; 
       break; 
      case "N": 
       this.Value = false; 
       break; 
     } 
    } 

    public void WriteXml(System.Xml.XmlWriter writer) { 
     string str = this.Value ? "Y" : "N"; 

     writer.WriteString(str); 
     writer.WriteEndElement(); 
    } 

    #endregion 
} 

Usted puede incluso hacer que la clase personalizada de un struct lugar, y proporcionar conversiones implícitas entre y bool para hacerlo aún más "transparente".

+1

Gran respuesta. Sin embargo, tuve que eliminar la declaración writer.WriteEndElement(); para evitar bloqueos durante la operación serializer.Serialize (...) – Hadron

7

La manera de hacerlo - que es subóptima pero no han encontrado una mejor manera - es definir dos propiedades:

[XmlRoot("ObjectSummary")] 
public class Summary 
{ 
    public string Name {get;set;} 
    [XmlIgnore] 
    public bool IsValid {get;set;} 
    [XmlElement("IsValid")] 
    public string IsValidXml {get{ ...};set{...};} 

} 

reemplazar ... con el código fácil de leer y escribir el IsValid valor a Y y N y lea de ello.

Cuestiones relacionadas