Cómo ocultar campos que aceptan valores NULL durante la serialización nula
Por ejemplo, la clase Persona tiene la siguiente definición:
[Serializable]
[XmlRoot(element name = " Person ")]
Personas de clase pública
{
Cadena pública Nombre { obtener configuración;}
Cadena pública Apellido { obtener configuración;}
int público? Edad { obtener configuración }
}
[Serializable]
[XmlRoot(nombre del elemento = " Persona ")]
Público personas de clase
{
Cadena pública Nombre { obtener configuración;}
Cadena pública Apellido { obtener configuración;}
pública int? Edad {get settings;}
}
El tipo de atributo Edad es un int que acepta valores NULL.
Nuestro código de creación de instancias es el siguiente:
var persona = nueva persona
{
FirstName = "First",
};
Personas. OutputXml(Console.out);
var persona = nueva persona
{
FirstName = "Primero",
};
Personas. OutputXml(console.out);
Entre ellos, el método OutputXml es un método de extensión que utiliza XmlSerializer para serializar objetos, definido específicamente como:
Public static void OutputXml ltT gt( this T dto, TextWriter textWriter)
{
var xmlTypeMapping = tipo de(T);
var serializador = nuevo serializador XML(xmlTypeMapping);
p>
var xmlns = new XmlSerializerNamespaces();
xmlns. add(String.null,String.null);
using(var escritor = nuevo escritor xmltext(escritor de texto){ Formato = Formato.Indent})
{
Serializador. Serialización(writer, dto, xmlns);
}
}
Public static void OutputXml ltT gt(this T dto, TextWriter textWriter)
{
var xmlTypeMapping = tipo de(T);
var serializador = nuevo serializador XML(xmlTypeMapping);
var xmlns = nuevo XmlSerializerNamespaces ( );
xmlns.
add(String.null,String.null);
using(var escritor = nuevo escritor xmltext(escritor de texto){ Formato = Formato.Indent})
{
Serializador. Serialización (escritor, dto, xmlns);
}
}
Utilice el método anterior para serializar el objeto persona, el resultado es:
Tenga en cuenta que, aunque la propiedad Edad está vacía, todavía está serializada en un xml extraño, que generalmente no es el resultado esperado. De hecho, la serialización de dos propiedades LastName que están vacías es exactamente lo que esperamos en la mayoría de los casos: las propiedades vacías se ignoran.
Por otro lado, si intentas serializar un atributo de clase en un atributo xml (en lugar de un elemento xml), ni siquiera funcionará. Por ejemplo, si modificamos la definición de la clase Persona a la siguiente forma para que pueda serializarse como un atributo xml:
[Serializable]
[XmlRoot(nombre del elemento = " Persona " )]
Personas de clase pública
{
[XmlAttribute]
Cadena pública Nombre { get settings } p >
[XmlAttribute]
Cadena pública Apellido { obtener configuración }
[XmlAttribute]
public int? Edad { obtener configuración }
}
[Serializable]
[XmlRoot(nombre del elemento = " Persona ")]
Público personas de clase
{
[XmlAttribute]
Cadena pública Nombre { get settings;}
[XmlAttribute]
Cadena pública Apellido { get settings;}
[XmlAttribute]
public int? age { get settings }
}
Xmlserializer ni siquiera puede serializar correctamente el mismo objeto de persona anterior y arroja el siguiente error "xmlattribute/xmltext no se puede utilizar para codificar tipos complejos" :
¿Cómo resolver los dos problemas anteriores?
1. Serializar las propiedades que aceptan valores NULL y generarlas como XmlElement.
Para ignorar la extraña salida de valores nulos al serializar propiedades que aceptan valores NULL, podemos definir un método especial ShouldSerializeAge en la clase Person que devuelve bool e implementar nuestras reglas de serialización en él:
[Serializable]
[XmlRoot(nombre del elemento = " Persona ")]
Persona de clase pública
{
Pública string Nombre {obtener configuración;}
Cadena pública Apellido {obtener configuración;}
public int? edad { obtener configuración }
public bool ShouldSerializeAge()
{
Devuelve la edad.
HasValue
}
}
[Serializable]
[XmlRoot(nombre del elemento = " Persona ")]
Personas de clase pública
{
Cadena pública Nombre { obtener configuración;}
Cadena pública Apellido { obtener configuración;} p>
público internacional? edad { obtener configuración }
public bool ShouldSerializeAge()
{
Devuelve la edad. HasValue
}
}
Aquí definimos la regla de serialización como: serializar edad no vacía. Tenga en cuenta que el nombre de este método debe comenzar con ShouldSerialize y estar concatenado con el nombre de la propiedad que requiere la regla personalizada. Un objeto persona serializado de esta manera es:
Una edad nula, como un apellido nulo, se ignora durante la serialización. ¡Exactamente lo que estábamos buscando!
2. Serializar el atributo anulable y generarlo como XmlAttribute.
Dado que los atributos que aceptan valores NULL no se pueden serializar directamente en XmlAttribute, debemos adoptar un enfoque indirecto: definir atributos indirectos. En este punto, podemos definir la clase de persona de la siguiente manera:
[Serializable]
[XmlRoot(element name = " Person ")]
Clase pública de personas
{
[XmlAttribute]
Cadena pública Nombre { get settings;}
[XmlAttribute]
Cadena pública Apellido { get settings;}
[XmlIgnore] // (4)
public int? Edad { get settings;}
[Atributo XML(AttributeName = " Age ")]//(1)
Valor de edad de cadena pública
{< / p>
Obtener
{
// (2)
Edad de retorno. ¿Tiene valor? edad. valor . ToString(): nulo
}
Configuración
{
int resultado;
/ / (3)
Edad = int. TryParse (valor, resultado de salida)? Resultado: (int?)null
}
}
}
[Serializable]
[XmlRoot (nombre del elemento = " Persona ")]
Persona de clase pública
{
[XmlAttribute]
Cadena pública Nombre { obtener configuración ;}
[XmlAttribute]
Cadena pública Apellido { get settings;}
[XmlIgnore] // (4)
público int? Edad { get settings;}
[Atributo XML(AttributeName = " Age ")]//(1)
Valor de edad de cadena pública
{< / p>
Obtener
{
// (2)
Edad de retorno. ¿Tiene valor? edad.
valor . ToString(): nulo
}
Configuración
{
int resultado;
/ / (3)
Edad = int. TryParse (valor, resultado de salida)? Resultado: (int?)nulo
}
}
}