XNA Creators Club Online
Page 1 of 1 (4 items)
Sort Posts: Previous Next

Automatic XNB Serialization and Collection types

Last post 09/11/2009 17:57 by Shawn Hargreaves. 3 replies.
  • 07/11/2009 1:20

    Automatic XNB Serialization and Collection types

    Hi all,

    I've recently experienced what seems to be odd inconsistencies between the capabilities of the IntermediateSerializer and the automatically generated XNB type readers. The issue pertains specifically to collection types. IntermediateSerializer handles collection-type properties adequately, for instance in the following:

     
    public class MyDataType 
      private readonly Collection<string> data = new Collection<string>(); 
     
      public Collection<string> Data 
      { 
        get { return this.data; } 
      } 


    Even though the property is read-only, since it is a collection type, both XmlSerializer and IntermediateSerializer follow the most sensible behavior of serializing collection items via the Add() method without needing to replace the backing store via a setter method.

    Apparently, however, automatically generated XNB serializers don't follow through on the promise. The above data type successfully compiles through the content pipeline, and serializes/deserializes correctly using IntermediateSerializer. However, upon runtime loading (via ContentManager) of a non-empty XML collection of the data-type above, the created runtime instance will have 0 items, indicating that the property data was somehow ignored.

    More specifically, the only way I got it to work with collection data-types was using the following declaration:

     
    public class MyDataType 
      public List<string> Data = new List<string>(); 


    This declaration successfully works with both IntermediateSerializer AND automatic XNB serialization. However it doesn't seem to work with the Collection generic base class. More freaky still is that if you use the first declaration pattern with a List<> instead of a Collection<> the ContentPipeline blows up with a circular dependency of some sort. Weird stuff.

    Has anyone experienced anything of the sort? I find these inconsistencies too hard to believe, but I managed to break it down to a really concrete and simple "now works/now doesn't work" example and I can't see where I could have gone wrong in my analysis.

    Thanks for all the help in advance and best regards,

    Gonçalo

  • 07/11/2009 18:24 In reply to

    Re: Automatic XNB Serialization and Collection types

    Automatic XNB serialization does not support Collection<T>.

    The automatic serializer works by getting all the public fields and properties of the type, looking up a ContentTypeWriter for each type it finds, and calling into that ContentTypeWriter.  For this to work, a type must follow certain rules:

    • All of its data is accesssible by public fields and properties
    • The types of these fields and properties are themselves serializable
      • Either because there is a built-in ContentTypeWriter for the member type
      • Or because the member type is itself compatible with the automatic serializer

    This is not the case for Collection<T>, because:

    • Its data is not accessible via simple fields or properties (you have to call GetEnumerator, but the automatic serializer knows nothing about that)
    • There is no built-in ContentTypeWriter for Collection<T>

    You have a couple of options:

    • Change your data to a type that does have a built-in ContentTypeWriter (eg. List<T> or T[])
    • Implement a ContentTypeWriter<Collection<T>> helper class
    XNA Framework Developer - blog - homepage
  • 08/11/2009 12:58 In reply to

    Re: Automatic XNB Serialization and Collection types

    Thanks for the clear-up :) I suspected something like this should be the case, but I found it odd since IntermediateSerializer does support it. I'm just thinking that people may find it strange if automatic XNB serialization does not support everything that IntermediateSerializer does.

    Another quick question: if I implement a custom ContentTypeWriter for collection classes, will the serializer look for it if all I have is a getter property? This appears to be the case for List<T>, but I'm not sure. Just asking because it is generally good practice to access collections only via getter properties.

    Thanks again for all the help and for all the serialization framework. Great stuff.

    Best regards,

    Gonçalo
  • 09/11/2009 17:57 In reply to

    Re: Automatic XNB Serialization and Collection types

    ChanceEncounter:
    I found it odd since IntermediateSerializer does support it.


    Yeah, that is a little odd.  IntermediateSerializer has a bunch more smarts than the XNB serializer, mostly to do with collections (it has special logic for understanding the ICollection interface).

    ChanceEncounter:
    I implement a custom ContentTypeWriter for collection classes, will the serializer look for it if all I have is a getter property?


    If your ContentTypeWriter overrides CanDeserializeIntoExistingObject to report true, then the serializer will be able to get the existing value of the property, then pass this as the existingInstance parameter when deserializing the object.

    If you leave the default CanDeserializeIntoExistingObject = false, the serializer will assume your deserializer does not support the existingInstance parameter, in which case it will not be able to serialize get-only properties of this type.
    XNA Framework Developer - blog - homepage
Page 1 of 1 (4 items) Previous Next