2012-07-04 13 views
39

tengo la clase siguiente:Serialize propiedad como atributo xml en el Elemento

[Serializable] 
public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public string SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public int SomeInfo { get; set; } 
} 

Qué (cuando se rellena con algunos datos de prueba) y serializado usando XmlSerializer.Serialize() da como resultado el siguiente código XML:

<SomeModel> 
    <SomeStringElementName>testData</SomeStringElementName> 
    <SomeInfoElementName>5</SomeInfoElementName> 
</SomeModel> 

lo que necesita tener es:

<SomeModel> 
    <SomeStringElementName Value="testData" /> 
    <SomeInfoElementName Value="5" /> 
</SomeModel> 

¿hay una manera de especificar esto como atributos ingenio ¿No estoy escribiendo mi propio código de serialización personalizado?

Respuesta

65

Tendrá clases contenedoras:

public class SomeIntInfo 
{ 
    [XmlAttribute] 
    public int Value { get; set; } 
} 

public class SomeStringInfo 
{ 
    [XmlAttribute] 
    public string Value { get; set; } 
} 

public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public SomeStringInfo SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public SomeIntInfo SomeInfo { get; set; } 
} 

o un enfoque más genérico, si lo prefiere:

public class SomeInfo<T> 
{ 
    [XmlAttribute] 
    public T Value { get; set; } 
} 

public class SomeModel 
{ 
    [XmlElement("SomeStringElementName")] 
    public SomeInfo<string> SomeString { get; set; } 

    [XmlElement("SomeInfoElementName")] 
    public SomeInfo<int> SomeInfo { get; set; } 
} 

Y luego:

class Program 
{ 
    static void Main() 
    { 
     var model = new SomeModel 
     { 
      SomeString = new SomeInfo<string> { Value = "testData" }, 
      SomeInfo = new SomeInfo<int> { Value = 5 } 
     }; 
     var serializer = new XmlSerializer(model.GetType()); 
     serializer.Serialize(Console.Out, model); 
    } 
} 

producirá:

<?xml version="1.0" encoding="ibm850"?> 
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <SomeStringElementName Value="testData" /> 
    <SomeInfoElementName Value="5" /> 
</SomeModel> 
+3

Sí, eso me da el esquema XML que necesito pero agrega un nivel innecesario de indirección y complejidad al modelo. Ahora, en lugar de Object.SomeProperty, tengo Object.SomeProperty.Value. Me doy cuenta de que podría no serlo en ambos sentidos con la serialización incorporada, pero esa es la esencia de la pregunta. – IUnknown

+2

Así es como funciona el serializador incorporado. –

+0

Sé que esto es algo antiguo, pero agregaría operaciones de conversión implícitas de 'T' a' SomeInfo 'y viceversa. – Shago

3

Tipo de, utilice XmlAttribute en lugar de XmlElement, pero no se verá como usted quiere. Se verá como la siguiente:

<SomeModel SomeStringElementName="testData"> 
</SomeModel> 

La única manera que puedo pensar para lograr lo que quiere (nativa) sería tener propiedades que apuntan a objetos con nombre SomeStringElementName y SomeInfoElementName donde la clase contenía un único captador denominado " valor". Puede dar un paso más y usar DataContractSerializer para que las clases contenedoras puedan ser privadas. XmlSerializer no leerá propiedades privadas.

// TODO: make the class generic so that an int or string can be used. 
[Serializable] 
public class SerializationClass 
{ 
    public SerializationClass(string value) 
    { 
     this.Value = value; 
    } 

    [XmlAttribute("value")] 
    public string Value { get; } 
} 


[Serializable]      
public class SomeModel      
{      
    [XmlIgnore]      
    public string SomeString { get; set; }      

    [XmlIgnore]      
    public int SomeInfo { get; set; } 

    [XmlElement] 
    public SerializationClass SomeStringElementName 
    { 
     get { return new SerializationClass(this.SomeString); } 
    }    
} 
+0

Hola Chris, sí, podría usar XmlAttribute pero como dijiste no da el resultado que necesito. Esperaba poder obtener lo que necesitaba sin escribir mi propio código de serialización. – IUnknown

+0

@IUnknown - Lancé una manera posible de lograr lo que quieres. No es bonito, crear clases para obtener un nodo, así que si alguien más conoce una mejor manera, yo también estaría interesado. –

Cuestiones relacionadas