.NET Compact Framework Serialization Bugs

XML Serialization in the .NET Compact Framework seems to be buggy enough that it is generally not useful if you need to serialize a class that conforms to a schema of some sort. If all you need to do is serialize and deserialize representations of a class you are probably fine. But if you need to use the serialized data to interoperate with a service (for example) it likely will not work.

Enums

I wrote previously about Problems with Enum Serialization on the .NET compact framework. To summarize: The XmlEnum attribute allows you to change the value that is serialized. One of the reasons to do this is to limit the valid values in the document. Of course, Enums have naming restrictions such as not being able to have spaces in them. So, one of the main reasons you would do this would be to put spaces in the name that was serialized.

The problem is that the XmlEnum under the .NET Compact Framework truncates the value at the first space. So, in the example below your Enums would serialize to “Some” and “Another” instead of the correct “Some Value” and “Another Value”.


public enum Foo {
[XmlEnum("Some Value")
Some,
[XmlEnum("Another Value")]
Other
}

Controlling Serialization of Value Types

.NET has reference types and value types. Reference types are stored on the heap and can be null. Value types are stored on the stack and can not be null. What is a value type and what is a reference type is not always obvious. int and double are value types but so is DateTime. string is a reference type though.

The serialization code is smart enough to not serialize null values. But what about those value types? They can not be null, so how do you determine if they should be serialized or not? There are two ways you can do it.

  1. DefaultValue
  2. PropertySpecified

DefaultValue

One way is to specify a default value. If the property has that default value it will not be serialized.

Example:

[XmlAttribute("age"), DefaultValue(-1)]
public int Age;

I have not found any problem with this on the .NET Compact Framework, but I haven’t used it extensively.
DefaultValue really does not make sense for every case. What about a value where negative, positive and zero all make sense? What about a boolean value where true and false are both meaningful and different from null? Valid values are really a business concept and many business concepts will not constrain them in such a way that you can specify a DefaultValue to control serialization, so this is not always useful.

See: more information on DefaultValue.

PropertySpecified

.NET serialization also allows you to specify a control value to check to see if a property should be serialized. The form of the control value is propertynameSpecified. It is a boolean value. If the value is false, then the property it controls will not be serialized. If the value, is true then it will be serialized.

Example:

[XmlIgnore]
public bool FooSpecified = false;

[XmlElement("foo)]
public int Foo {
get { return this.foo; }
set {
this.foo = value;
this.FooSpecified = true;
}
}

This is fine in the full framework. The problem is with the .NET Compact Framework. When the serializer comes across a propertynameSpecified value that is false, the serialization of that class stops. This means if you have 5 properties and the second property has a control value set to false, only the first value will be serialized!

Coming Soon

In a future post, I will write about how you can relatively easily write your own XML Serializer for the .NET Compact Framework in about 500 lines of code.

Update: follow-up post on Writing a Custom XML Serializer has been posted.

5 thoughts on “.NET Compact Framework Serialization Bugs”

  1. Phil,
    Thanks for the advice, but unfortunately for this project we were interoperating with a Web Service, so we were mapping between objects and the XML that we needed to send back and forth between the handheld and the service. So binary wouldn’t work in this case…

  2. Do you know, who I can do that in compact framework?
    because BinaryFormatter doesn’t exist.

    ///
    /// Implementacion de la interfaz IClonable.
    /// Retorna un objeto clonado.
    public object Clone()
    {
    MemoryStream buffer = new MemoryStream();
    BinaryFormatter format = new BinaryFormatter();
    format.Serialize(buffer, this);
    buffer.Position = 0;
    return format.Deserialize(buffer);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>