Using C# .NET 2.0, I have a composite data class that does have the [Serializable]
attribute on it. I am creating an XMLSerializer
class and passi
Also note that you cannot serialize user interface controls and that any object you want to pass onto the clipboard must be serializable otherwise it cannot be passed across to other processes.
I have a slightly different solution to all described here so far, so for any future civilisation here's mine!
I had declared a datatype of "time" as the original type was a TimeSpan
and subsequently changed to a String
:
[System.Xml.Serialization.XmlElementAttribute(DataType="time", Order=3)]
however the actual type was a string
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
by removing the DateType
property the Xml
can be serialized
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string TimeProperty {
get {
return this.timePropertyField;
}
set {
this.timePropertyField = value;
this.RaisePropertyChanged("TimeProperty");
}
}
If you need to handle specific attributes (i.e. Dictionary, or any class), you can implement the IXmlSerialiable interface, which will allow you more freedom at the cost of more verbose coding.
public class NetService : IXmlSerializable
{
#region Data
public string Identifier = String.Empty;
public string Name = String.Empty;
public IPAddress Address = IPAddress.None;
public int Port = 7777;
#endregion
#region IXmlSerializable Implementation
public XmlSchema GetSchema() { return (null); }
public void ReadXml(XmlReader reader)
{
// Attributes
Identifier = reader[XML_IDENTIFIER];
if (Int32.TryParse(reader[XML_NETWORK_PORT], out Port) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_PORT);
if (IPAddress.TryParse(reader[XML_NETWORK_ADDR], out Address) == false)
throw new XmlException("unable to parse the element " + typeof(NetService).Name + " (badly formatted parameter " + XML_NETWORK_ADDR);
}
public void WriteXml(XmlWriter writer)
{
// Attributes
writer.WriteAttributeString(XML_IDENTIFIER, Identifier);
writer.WriteAttributeString(XML_NETWORK_ADDR, Address.ToString());
writer.WriteAttributeString(XML_NETWORK_PORT, Port.ToString());
}
private const string XML_IDENTIFIER = "Id";
private const string XML_NETWORK_ADDR = "Address";
private const string XML_NETWORK_PORT = "Port";
#endregion
}
There is an interesting article, which show an elegant way to implements a sophisticated way to "extend" the XmlSerializer.
The article say:
IXmlSerializable is covered in the official documentation, but the documentation states it's not intended for public use and provides no information beyond that. This indicates that the development team wanted to reserve the right to modify, disable, or even completely remove this extensibility hook down the road. However, as long as you're willing to accept this uncertainty and deal with possible changes in the future, there's no reason whatsoever you can't take advantage of it.
Because this, I suggest to implement you're own IXmlSerializable
classes, in order to avoid too much complicated implementations.
...it could be straightforward to implements our custom XmlSerializer
class using reflection.
I've discovered that the Dictionary class in .Net 2.0 is not serializable using XML, but serializes well when binary serialization is used.
I found a work around here.
I had a situation where the Order was the same for two elements in a row
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "SeriousInjuryFlag")]
.... some code ...
[System.Xml.Serialization.XmlElementAttribute(IsNullable = true, Order = 0, ElementName = "AccidentFlag")]
When I changed the code to increment the order by one for each new Property in the class, the error went away.
Remember that serialized classes must have default (i.e. parameterless) constructors. If you have no constructor at all, that's fine; but if you have a constructor with a parameter, you'll need to add the default one too.