如何使用.NET XmlSerializer使值类型为空?

让我们假设我有这个对象:

[Serializable] public class MyClass { public int Age { get; set; } public int MyClassB { get; set; } } [Serializable] public class MyClassB { public int RandomNumber { get; set; } } 

XmlSerializer会像这样序列化对象:

  0  4234   

我怎样才能使该物业成为可空? IE:当它低于0时,没有序列化属性Age?

我尝试使用Nullable,但它将我的对象序列化为:

    4234   

通过阅读MSDN文档,我发现了这个:

您不能将IsNullable属性应用于键入为值类型的成员,因为值类型不能包含nullNothingnullptra null引用(在Visual Basic中为Nothing)。 此外,对于可为空的值类型,您不能将此属性设置为false。 当这些类型为nullNothingnullptra null引用(在Visual Basic中为Nothing)时,它们将通过将xsi:nil设置为true来序列化。

来源: http : //msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.isnullable.aspx

我理解值类型不能设置为null。 值类型始终设置为某个值。 序列化不能根据它的当前值决定是否序列化它。

我尝试了属性,但它没有成功。 我尝试创建一个agecontainer对象并使用属性操作它的序列化,但它没有成功。

我真正想要的是:

   4234   

当属性Age低于0(零)时。


看起来你必须实现自定义序列化。

是的,那也是我的意思,但我想在没有它的情况下离开。

在应用程序中,对象要复杂得多,我不想自己处理序列化。

我刚发现了这个。 XmlSerialier查找XXXSpecified布尔属性以确定是否应包含它。 这应该很好地解决问题。

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

certificate:

 static string Serialize(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); // = 0 Serialize(withAge); // = 200 } 

编辑 :是的,这是一个记录的function。 请参阅XmlSerializer的MSDN条目

另一种选择是使用特殊模式来创建XmlSerializer可识别的布尔字段,并将XmlIgnoreAttribute应用于该字段。 该模式以propertyNameSpecified的forms创建。 例如,如果有一个名为“MyFirstName”的字段,您还将创建一个名为“MyFirstNameSpecified”的字段,该字段指示XmlSerializer是否生成名为“MyFirstName”的XML元素。

将Samuel的答案和Greg Beech的评论扩展到布尔属性的情况:如果属性是bool类型,那么你就不能在propertySpecified属性中编写一个简单的测试。

解决方案是使用Nullable 类型,然后propertySpecified属性中的测试只是property.HasValue。 例如

 using System.Xml.Serialization; public class Person { public bool? Employed { get; set; } [XmlIgnore] public bool EmployedSpecified { get { return Employed.HasValue; } } } 

对数值属性使用可空类型(由Greg Beech建议)的替代方法是将value属性设置为无效的默认值,例如-1,如下所示:

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

您可以使用XmlElementAttribute.IsNullable

 [Serializable] public class MyClass { [XmlElement(IsNullable = true)] public int? Age { get; set; } public int MyClassB { get; set; } } 

这应该有助于Make Age int? 和..

 public bool ShouldSerializeAge() { return Age.HasValue; } 

..的确意味着将ShouldSerializeXXX方法添加到您的class级!

忘记Nullable …… ShouldSerializeXXX是一个非常好的解决方案。 这里的年龄将根据您的情况系列化。

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

如果为某个元素设置’minoccurs’属性为’minoccurs =“0”’,xsd.exe将自动生成XXXSpecified属性和访问器…如果您使用模式定义xml / class