2009-08-18 5 views
61

Bitte beachten Sie die folgenden Betrag Werttyp Eigenschaft, die als Nullable-XmlElement gekennzeichnet:Unterdrückt Null Wertetypen von durch XmlSerializer ausgesendet wird

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

Wenn ein Nullable-Wertetyp auf null gesetzt wird, werden die C# XmlSerializer Ergebnis aussieht wie das Folgende:

Anstatt dieses Element zu emittieren, möchte ich, dass der XmlSerializer das Element vollständig unterdrückt. Warum? Wir verwenden Authorize.NET für Online-Zahlungen und Authorize.NET lehnt die Anfrage ab, wenn dieses Nullelement existiert.

Die aktuelle Lösung/Problemumgehung besteht darin, die Eigenschaft Betrag Werttyp überhaupt nicht zu serialisieren. Stattdessen haben wir eine komplementäre Eigenschaft, SerializableAmount, erstellt, die auf Amount basiert und stattdessen serialisiert wird. Da SerializableAmount vom Typ String ist, die wie Referenztypen vom XmlSerializer unterdrückt werden, wenn standardmäßig null, funktioniert alles gut.

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

Natürlich ist dies nur ein Workaround. Gibt es eine sauberere Möglichkeit, die Ausgabe von Elementen vom Typ Nullwert zu unterdrücken?

+5

btw; "Betrag" (für Zahlungen) kann besser als "dezimal" sein. –

+1

Guter Punkt: Fließkomma Geld ist böse. –

+0

@Marc Danke, dass du das auch rausrufst. –

Antwort

130

Versuche Zugabe:

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

Es gibt eine Reihe von Mustern durch Teile des Rahmens erkannt. Für Informationen, XmlSerializer sucht auch nach public bool AmountSpecified {get;set;}.

Voll Beispiel (auch decimal schaltend):

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

Mehr Informationen über ShouldSerialize* on MSDN.

+3

Hallo Marc, deshalb liebe ich SO ... Du lernst so etwas. Ich habe jedoch ein paar Fragen. Ich kann die folgende Dokumentation dieses Features nur in msdn finden: http://msdn.microsoft.com/en-us/library/53b8022e.aspx Kennen Sie eine * echte * Dokumentation? Da dieses Feature so schlecht dokumentiert ist, würde ich mich ein bisschen schmutzig fühlen. Ist es "sicher", ein scheinbar undokumentiertes Feature wie dieses zu verwenden? – JohannesH

+5

Wow, das würde ich zutiefst dunkel nennen. Cool, dass du es gefunden hast. –

+0

Danke Marc. Nun, da Sie mir gesagt haben, wonach ich suchen soll, habe ich die MSDN-Referenz auf dem "property + specified" -Muster von XmlSerializer gefunden. Hier ist es: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx. Es ist sogar schwierig zu finden, wenn Sie die richtige MSDN-Referenzseite finden, wenn Sie mich fragen. :) Danke noch einmal. –

6

Es gibt auch eine alternative

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

Verwenden

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

Sie können zu bekommen versuchen Sie dies:

xml.Replace("xsi:nil=\"true\"", string.Empty);

Verwandte Themen