web-dev-qa-db-fra.com

Supprimer les types de valeur nulle d'être émis par XmlSerializer

Veuillez considérer la propriété de type de valeur Amount suivante qui est marquée en tant que XmlElement nullable: 

[XmlElement(IsNullable=true)] 
public double? Amount { get ; set ; }

Lorsqu'un type de valeur nullable est défini sur null, le résultat de C # XmlSerializer se présente comme suit: 

<amount xsi:nil="true" />

Plutôt que d’émettre cet élément, je voudrais que XmlSerializer supprime complètement l’élément. Pourquoi? Nous utilisons Authorize.NET pour les paiements en ligne et Authorize.NET rejette la demande si cet élément null existe. 

La solution/solution actuelle consiste à ne pas sérialiser la propriété de type de valeur Amount. À la place, nous avons créé une propriété complémentaire, SerializableAmount, qui est basée sur Amount et est sérialisée à la place. SerializableAmount étant de type String, qui, comme les types de référence, est supprimé par XmlSerializer si la valeur est null par défaut, tout fonctionne parfaitement. 

/// <summary>
/// Gets or sets the amount.
/// </summary>
[XmlIgnore]
public double? Amount { get; set; }

/// <summary>
/// Gets or sets the amount for serialization purposes only.
/// This had to be done because setting value types to null 
/// does not prevent them from being included when a class 
/// is being serialized.  When a nullable value type is set 
/// to null, such as with the Amount property, the result 
/// looks like: &gt;amount xsi:nil="true" /&lt; which will 
/// cause the Authorize.NET to reject the request.  Strings 
/// when set to null will be removed as they are a 
/// reference type.
/// </summary>
[XmlElement("amount", IsNullable = false)]
public string SerializableAmount
{
    get { return this.Amount == null ? null : this.Amount.ToString(); }
    set { this.Amount = Convert.ToDouble(value); }
}

Bien sûr, ceci est juste une solution de contournement. Existe-t-il un moyen plus efficace de supprimer l’émission d’éléments de type valeur null?

63
Ben Griswold

Essayez d'ajouter:

public bool ShouldSerializeAmount() {
   return Amount != null;
}

Il existe un certain nombre de modèles reconnus par certaines parties du cadre. Pour info, XmlSerializer recherche également public bool AmountSpecified {get;set;}.

Exemple complet (passage également à decimal):

using System;
using System.Xml.Serialization;

public class Data {
    public decimal? Amount { get; set; }
    public bool ShouldSerializeAmount() {
        return Amount != null;
    }
    static void Main() {
        Data d = new Data();
        XmlSerializer ser = new XmlSerializer(d.GetType());
        ser.Serialize(Console.Out, d);
        Console.WriteLine();
        Console.WriteLine();
        d.Amount = 123.45M;
        ser.Serialize(Console.Out, d);
    }
}

Plus d'informations sur ShouldSerialize * sur MSDN .

132
Marc Gravell

Il y a aussi une alternative pour obtenir 

 <amount /> instead of <amount xsi:nil="true" />

Utilisation

[XmlElement("amount", IsNullable = false)]
public string SerializableAmount
{
    get { return this.Amount == null ? "" : this.Amount.ToString(); }
    set { this.Amount = Convert.ToDouble(value); }
}
6
mko