Let\'s suppose I have this object:
[Serializable]
public class MyClass
{
public int Age { get; set; }
public int MyClassB { get; set; }
}
[Serializab
Extending Samuel's answer and Greg Beech's comment to the case of a boolean property: if the property is of type bool then you can't write a simple test in the propertySpecified property.
A solution is to use a Nullable<bool> type, then the test in the propertySpecified property is simply property.HasValue. e.g.
using System.Xml.Serialization;
public class Person
{
public bool? Employed { get; set; }
[XmlIgnore]
public bool EmployedSpecified { get { return Employed.HasValue; } }
}
An alternative to using a nullable type for a numeric property (suggested by Greg Beech) is to set the value property to an invalid default value, such as -1, as follows:
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; } }
}
You need to do custom XML serialization; see IXmlSerializer.
public class MyClass : IXmlSerializable
{
public int Age { get; set; }
public MyClassB MyClassB { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
// http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
return null;
}
public void ReadXml(XmlReader reader)
{
if (reader.IsStartElement("Age"))
Age = reader.ReadContentAsInt();
var serializer = new XmlSerializer(typeof(MyClassB));
MyClassB = (MyClassB)serializer.Deserialize(reader);
}
public void WriteXml(XmlWriter writer)
{
if (Age > 0)
{
writer.WriteStartElement("Age");
writer.WriteValue(Age);
writer.WriteEndElement();
}
var serializer = new XmlSerializer(typeof(MyClassB));
serializer.Serialize(writer, MyClassB);
}
}
Forget about Nullable ... ShouldSerializeXXX is a pretty solution. Here Age will be serialized upon your 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 will autogenerate the XXXSpecified property and accessors if you set the 'minoccurs' attribute as 'minoccurs="0"' for an element ... if you are using a schema to define your xml/class
I just discovered this. XmlSerialier
looks for a XXXSpecified
boolean property to determine if it should be included. This should solve the problem nicely.
[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; }
}
Proof:
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>
}
Edit: Yes, it is a documented feature. See the MSDN entry for XmlSerializer
Another option is to use a special pattern to create a Boolean field recognized by the XmlSerializer, and to apply the XmlIgnoreAttribute to the field. The pattern is created in the form of propertyNameSpecified. For example, if there is a field named "MyFirstName" you would also create a field named "MyFirstNameSpecified" that instructs the XmlSerializer whether to generate the XML element named "MyFirstName".
You can use XmlElementAttribute.IsNullable:
[Serializable]
public class MyClass
{
[XmlElement(IsNullable = true)]
public int? Age { get; set; }
public int MyClassB { get; set; }
}