Comment faire une valeur type nullable with.NET XmlSerializer?
supposons que j'ai cet objet:
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
}
[Serializable]
public class MyClassB
{
public int RandomNumber { get; set; }
}
le XmlSerializer sérialisera l'objet comme ceci:
<MyClass>
<Age>0</age>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
Comment puis-je rendre l'âge de la propriété nullable? IE: ne pas sérialiser L'Âge de la propriété quand il est inférieur à 0?
j'ai essayé avec le Nullable, mais il sérialise mon objet comme cela:
<MyClass>
<Age d5p1:nil="true" />
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
en lisant la documentation du MSDN, j'ai trouvé ceci:
vous ne pouvez pas appliquer la propriété IsNullable à un membre tapé comme type de valeur parce qu'un type de valeur ne peut pas contenir nullNothingnullptra référence nulle (rien dans Visual Basic). De plus, vous ne pouvez pas définir cette propriété à false pour les types de valeur nulles. Lorsque ces types sont nullNothingnullptra référence nulle (rien dans Visual Basic), ils seront sérialisés en mettant xsi:nil à true.
source: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx
je comprends qu'un type de valeur ne peut pas être défini à null. Un valuetype est toujours quelque chose. La sérialisation ne peut pas prendre la décision de sérialiser ou pas basée sur sa valeur actuelle.
j'ai essayé avec les attributs, mais ça n'a pas fonctionné. J'ai essayé de créer un objet agecontainer et de manipuler sa sérialisation avec des attributs, mais il n'a pas fonctionné.
ce que je veux vraiment c'est:
<MyClass>
<MyClassB>
<RandomNumber>4234</RandomNumber>
</MyClassB>
</MyClass>
lorsque l'Âge de la propriété est inférieur à 0 (zéro).
semble que vous aurez à mettre en œuvre la sérialisation personnalisée.
Oui, c'est ce que je pense aussi, mais j'aimerais m'en passer.
Dans l'application, l'objet est beaucoup plus complexe, et je voudrais ne pas gérer la sérialisation moi-même.
6 réponses
je viens de découvrir ceci. XmlSerialier
cherche une propriété booléenne XXXSpecified
pour déterminer si elle doit être incluse. Cela devrait résoudre le problème gentiment.
[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; }
}
preuve:
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>
}
modifier : Oui, c'est une fonctionnalité documentée. Voir la rubrique MSDN pour XmlSerializer
une Autre option est d'utiliser un modèle spécial pour créer un champ booléen reconnu par le XmlSerializer, et pour appliquer le XmlIgnoreAttribute au champ. Le modèle est créé sous la forme de propertynamespécified. Par exemple, s'il y a un champ nommé "MyFirstName", vous créerez aussi un champ nommé "Myfirstnamespécified" qui indique au XmlSerializer s'il doit générer l'élément XML nommé "MyFirstName".
extension de la réponse de Samuel et du commentaire de Greg Beech au cas d'une propriété booléenne: si la propriété est de type bool alors vous ne pouvez pas écrire un test simple dans la propriété propertys specified.
une solution est d'utiliser un type Nullable
using System.Xml.Serialization;
public class Person
{
public bool? Employed { get; set; }
[XmlIgnore]
public bool EmployedSpecified { get { return Employed.HasValue; } }
}
une alternative à l'utilisation d'un type nul pour une propriété numérique (suggéré par Greg Beech) est de définir la propriété value à une valeur par défaut non valide, telle que -1, comme suit:
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; } }
}
vous pouvez utiliser Xmdelementattribute.IsNullable :
[Serializable]
public class MyClass
{
[XmlElement(IsNullable = true)]
public int? Age { get; set; }
public int MyClassB { get; set; }
}
cela devrait aider Faire de l'Âge de l'int? et..
public bool ShouldSerializeAge() { return Age.HasValue; }
..cela signifie ajouter les méthodes ShouldSerializeXXX à votre classe!
d'Oublier les valeurs null ... ShouldSerializeXXX est une jolie solution. Ici L'Âge sera sérialisé sur votre condition.
[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; }
}
xsd.exe va autogénérer la propriété et les accesseurs XXXS spécifiés si vous définissez l'attribut 'minoccurs' comme 'minoccurs="0"' pour un élément ... si vous utilisez un schéma pour définir votre xml/classe