November 5th, 2007

Workaround for XmlSerializer T[] and List bug

Andrew Arnott
Principal Software Engineer

The XmlSerializer in NetCF 2.0 has a bug where if a single serialization requires reflecting into types that use a mixture of Collection<T>-like types for the same T the XmlSerializer will throw an exception.  Here an example where CF 2.0 would crash:

public class SerializingType1 {
   public string[] FirstNames;
   public List<string> PhoneNumbers;
}

This type would fail to serialize under NetCF 2.0 because T = string would appear in two kinds of collections. This next example would also fail if you were serializing TypeA, because it contains a TypeB instance which has the another kind of T collection.

public class TypeA {
   public string[] FirstNames;
   public TypeB b;
}
public class TypeB {
   public List<string> PhoneNumbers;
}

If you can change the public API to use all T[] or List<T> and avoid the mixture, you’ve worked around the problem. So this would be the simplest workaround:

public class SerializingType1 {
   public List<string> FirstNames;
   public List<string> PhoneNumbers;
}

If you can’t change the public API to maintain compatibility for your customers, here’s another workaround that will eliminate the mixture for the XmlSerializer but keep the mixture for your customers.

public class SerializingType1 {
   [XmlIgnore]
   public string[] FirstNames {
      get { return firstNamesHiddenList != null ? firstNamesHiddenList.ToArray() : null; }
      set { firstNamesHiddenList = value != null ? new List<string>(value) : null; }
   }
   [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
   [XmlArray("FirstNames")]
   [Obsolete("This member is for internal use only.")]
   public List<string> firstNamesHiddenList;
   public List<string> PhoneNumbers;
}

This will make the XmlSerializer work, and the API to the customer appear to be the same, except for a public member that they should never use directly that is only there (and public) because the XmlSerializer requires it.  EditorBrowsableAttribute and ObsoleteAttribute are there to help the customer to not run into that member and use it when you didn’t intend them to. 

This bug is fixed in .NET Compact Framework 3.5.

Author

Andrew Arnott
Principal Software Engineer

Principal Software Engineer and OSS contributor. Visual Studio Platform.

0 comments

Discussion are closed.