c# - objeto - ¿Cómo hacer que un tipo de valor sea anulable con.NET XmlSerializer?
serializar objeto c# xml (6)
Acabo de descubrir esto. XmlSerialier
busca una propiedad booleana XXXSpecified
para determinar si debería incluirse. Esto debería resolver el problema muy bien.
[Serializable]
public class MyClass
{
public int Age { get; set; }
[XmlIgnore]
public bool AgeSpecified { get { return Age >= 0; } }
public int MyClassB { get; set; }
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
Prueba:
static string Serialize<T>(T obj)
{
var serializer = new XmlSerializer(typeof(T));
var builder = new StringBuilder();
using (var writer = new StringWriter(builder))
{
serializer.Serialize(writer, obj);
return builder.ToString();
}
}
static void Main(string[] args)
{
var withoutAge = new MyClass() { Age = -1 };
var withAge = new MyClass() { Age = 20 };
Serialize(withoutAge); // = <MyClass><MyClassB>0</MyClassB></MyClass>
Serialize(withAge); // = <MyClass><Age>20</Age><MyClassB>0</MyClassB></MyClass>
}
Edición : Sí, es una característica documentada. Ver la entrada de MSDN para XmlSerializer
Otra opción es usar un patrón especial para crear un campo booleano reconocido por el XmlSerializer y aplicar el atributo XmlIgnoreAttribute al campo. El patrón se crea en la forma de propertyNameSpecified. Por ejemplo, si hay un campo llamado "MyFirstName", también creará un campo llamado "MyFirstNameSpecified" que le indica al XmlSerializer si debe generar el elemento XML llamado "MyFirstName".
Supongamos que tengo este objeto:
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
El XmlSerializer serializará el objeto así:
<MyClass>
<Age>0</age>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
¿Cómo puedo hacer la propiedad Age nullable? IE: para no serializar la propiedad Age cuando está por debajo de 0?
Intenté con el Nullable, pero serializó mi objeto así:
<MyClass>
<Age d5p1:nil="true" />
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
Al leer la documentación de MSDN encontré esto:
No puede aplicar la propiedad IsNullable a un miembro escrito como tipo de valor porque un tipo de valor no puede contener nullNothingnullptra null reference (Nothing en Visual Basic). Además, no puede establecer esta propiedad en falso para los tipos de valores anulables. Cuando tales tipos son nullNothingnullptra null reference (Nothing en Visual Basic), se serializarán estableciendo xsi: nil en true.
fuente: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx
Entiendo que un tipo de valor no se puede establecer en nulo. Un tipo de valor siempre se establece en algo. La serialización no puede tomar la decisión de serializarla o no según su valor actual.
Intenté con los atributos, pero no funcionó. Intenté crear un objeto de contenedor y manipular su serialización con atributos, pero no funcionó.
Lo que realmente quiero es:
<MyClass>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
Cuando la propiedad Age está por debajo de 0 (cero).
Parece que tendrás que implementar una serialización personalizada.
Sí, eso es lo que yo también pensé, pero me gustaría escaparme sin eso.
En la aplicación, el objeto es mucho más complejo, y me gustaría no manejar la serialización por mi cuenta.
Esto debería ayudar a Make Age int? y..
public bool ShouldSerializeAge() { return Age.HasValue; }
..it significa agregar los métodos ShouldSerializeXXX a tu clase!
Extendiendo la respuesta de Samuel y el comentario de Greg Beech al caso de una propiedad booleana: si la propiedad es de tipo bool, no puede escribir una prueba simple en la propiedad propertySpecified.
Una solución es utilizar un tipo <bool> Nullable, entonces la prueba en la propiedad propertySpecified es simplemente property.HasValue. p.ej
using System.Xml.Serialization;
public class Person
{
public bool? Employed { get; set; }
[XmlIgnore]
public bool EmployedSpecified { get { return Employed.HasValue; } }
}
Una alternativa al uso de un tipo anulable para una propiedad numérica (sugerida por Greg Beech) es establecer la propiedad de valor en un valor predeterminado no válido, como -1, de la siguiente manera:
using System.ComponentModel;
using System.Xml.Serialization;
public class Person
{
[DefaultValue(-1)]
public int Age { get; set; }
[XmlIgnore]
public bool AgeSpecified { get { return Age >= 0; } }
}
Olvídate de Nullable ... ShouldSerializeXXX es una solución bonita. Aquí la edad será serializada a su condición.
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
#region Conditional Serialization
public bool ShouldSerializeAge() { return age > 0; }
#endregion
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
Puede usar http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx :
[Serializable]
public class MyClass
{
[XmlElement(IsNullable = true)]
public int? Age { get; set; }
public int MyClassB { get; set; }
}
xsd.exe generará automáticamente la propiedad XXXSpecified y los accesores si establece el atributo ''minoccurs'' como ''minoccurs = "0"'' para un elemento ... si está usando un esquema para definir su xml / class