4 Things to know about SuspensionManager

The default Visual C# app templates created by VS in Windows 8.1 make use of the SuspensionManager helper class (in the Common folder) to handle how your app can save it’s state when Windows puts it in the Suspended state. As you might expect, it serializes your data to disk, then deserializes it back for you when your app Resumes. How? DataContractSerializer. It’s a good way. Here’s what you need to know:

  1. DataContractSerializer (and thus SuspensionManager) needs to know about any custom types before it can work with your objects. Tell it in your App() constructor via:
    SuspensionManager.KnownTypes.Add(typeof(ObservableCollection<CarViewModel>));
    SuspensionManager.KnownTypes.Add(typeof(CarViewModel));
    
  2. Types serialized by DataContractSerializer must be decorated with the DataContractAttribute.
    [DataContract]
    public CarViewModel { ... }
    
  3. Member fields/properties of these types must be decorated with the DataMemberAttribute. By default, none of your objects members are serialized, you must use the attribute to include them. The cool thing is, you can apply it to a private member.
  4. When deserializing, the default constructor of your object will not be called. Weird, seemingly illegal, but it makes sense — say your object contains a state machine, and the default constructor sets the state machine to position 0. If you serialize your object with the state machine at position 3, you want it to deserialize in the same position.

If your types can deal with the constructor not being called, easy-as-pie, you are done! But, what if you need to run initialization logic on deserialization? For example, my CarViewModel has a private Car field. All of my public properties are simply meta-data based off of the Car. It’s more convenient for me to simply serialize only the Car, then re-initialize my meta-data once the Car is returned to me in deserialization.

Have no fear, just use the OnDeserializedAttribute above a method, like so:

[OnDeserialized]
internal void Initialize(StreamingContext context)
{
    // this.car is already in place, we've been deserialized
    InitializeDataFromCar(this.car);
}

Need more access? No problem, you’ve got an attribute for before serialization, after serialization, before deserialization, and after deserialization. You can find them all under the System.Runtime.Serialization namespace.