web-dev-qa-db-fra.com

Sérialiser la propriété en tant qu'attribut XML dans Element

J'ai la classe suivante:

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

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

Ce qui (lorsqu'il est rempli avec des données de test) et sérialisé à l'aide de XmlSerializer.Serialize () résulte en XML suivant:

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

Ce dont j'ai besoin, c'est:

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

Est-il possible de spécifier cela en tant qu'attributs sans écrire mon propre code de sérialisation personnalisé?

56
IUnknown

Vous aurez besoin de classes de wrapper:

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

ou une approche plus générique si vous préférez:

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

Et alors:

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

produira:

<?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>
83
Darin Dimitrov

En quelque sorte, utilisez XmlAttribute au lieu de XmlElement, mais cela ne ressemblera pas à ce que vous voulez. Cela ressemblera à ceci:

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

La seule façon pour moi d’atteindre ce que vous voulez (nativement) serait d’avoir des propriétés pointant sur des objets nommés SomeStringElementName et SomeInfoElementName où la classe contenait un seul getter nommé "valeur". Vous pouvez aller plus loin et utiliser DataContractSerializer afin que les classes de wrapper puissent être privées. XmlSerializer ne lira pas les propriétés privées.

// 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); }
    }               
}
5
Chris Gessler