2009-08-18 8 views
61

Por favor, considere la siguiente propiedad tipo de valor Monto que está marcado como XmlElement anulable:reprimir valor nulo Tipos de ser emitida por XmlSerializer

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

Cuando un tipo de valor anulable se establece en NULL, el C# XmlSerializer resultado se ve como la siguiente:

<amount xsi:nil="true" /> 

vez de emitir a este elemento, me gustaría XmlSerializer para suprimir el elemento completo. ¿Por qué? Estamos utilizando Authorize.NET para pagos en línea y Authorize.NET rechaza la solicitud si este elemento nulo existe.

La solución/solución alternativa actual es no serializar en absoluto la propiedad Tipo de valor de cantidad. En su lugar, hemos creado una propiedad complementaria, SerializableAmount, que se basa en Cantidad y se serializa en su lugar. Dado que SerializableAmount es de tipo String, que como tipos de referencia similares son suprimidos por XmlSerializer si nulo por defecto, todo funciona bien.

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

Por supuesto, esto es solo una solución. ¿Hay alguna manera más limpia de suprimir la emisión de elementos del tipo de valor nulo?

+5

por cierto; "amount" (para pagos) puede ser mejor como 'decimal'. –

+1

Buen punto: el dinero en coma flotante es malo. –

+0

@Marc Gracias por llamar a eso también. –

Respuesta

130

Trate de añadir:

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

Hay una serie de patrones reconocidos por partes del marco. Para obtener información, XmlSerializer también busca public bool AmountSpecified {get;set;}.

ejemplo completo (también cambiar a 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); 
    } 
} 

Más información sobre ShouldSerialize* on MSDN.

+3

Hola Marc, es por eso que amo TAN ... Aprendes algo como esto. Aunque tengo un par de preguntas. Solo puedo encontrar la siguiente documentación de esta característica en msdn: http://msdn.microsoft.com/en-us/library/53b8022e.aspx ¿conoce alguna documentación * real *? Además, dado que esta función está tan poco documentada, me sentiría un poco sucio al usarla. ¿Es "seguro" utilizar una función aparentemente indocumentada como esta? – JohannesH

+5

Guau, eso es lo que llamaría profundamente oscuro. Aunque es genial que lo hayas encontrado. –

+0

Gracias Marc. Ahora que me dijiste qué buscar, creo que encontré la referencia de MSDN en el patrón "propiedad + especificada" de XmlSerializer. Aquí está: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx. Incluso es difícil encontrarlo una vez que encuentre la página de referencia de MSDN correcta si me lo pregunta. :) Gracias de nuevo. –

6

También hay una alternativa para conseguir

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

Uso

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

puede probar esto:

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

Cuestiones relacionadas