.NET Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

Windows 8 Snippet: Proper Serialization

03.18.2013
| 2772 views |
  • submit to reddit

This week's Windows 8 snippet covers one of the most widely used tasks, especially when it comes to local data storage and retrieval - serialization. I got tired of re-writing the same routine over and over again, so here are the code fragments for my and your record.

Serialization:

public static async Task<bool> SerializeToFile<T>(string fileName, T serializationSource)
{
    try
    {
        StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
            fileName, CreationCollisionOption.ReplaceExisting);

        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            serializer.WriteObject(stream.AsStreamForWrite(), serializationSource);

        }
        return true;

    }
    catch
    {
        return false;
    }
}
Notice that I am making this as flexible as possible. The normal approach for a lot of developers would be passing a defined type as the serialization source. Which is a viable solution for small applications, but is bound to be too cumbersome for larger solutions where you will have to serialize multiple types to multiple destinations. Hence, I am also requiring the developer to specify the file name that I will be using as the destination. 

Also, notice that I am using Windows.Storage.ApplicationData.Current.LocalFolder as the root. That way, I do not need to declare any custom capabilities in order for this function to work, as it will push the data in the application-designated space. This can be customized by requesting the StorageFolder instance to be written to.

Also pay close attention to what the function is returning. Do not, I repeat, DO NOT use async void. If the task is successful, it will signal this via a bool value. Same applies to case where it might fail (e.g. not enough storage space).

Deserialization:

public static async Task<T> DeserializeFromFile<T>(string fileName)
{
    T returnable;

    try
    {
        StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync(fileName);

        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(T));
            returnable = (T)serializer.ReadObject(stream.AsStream());
        }
        return returnable;
    }
    catch
    {
        return default(T);
    }
}

Here I am taking a similar approach when it comes to getting the type-based data back. There are no pre-defined types - everything is inferred from the generic T. If the data is correctly serialized, I am returning the instance that I managed to obtain. Otherwise the default value is returned for the type passed, which could be null for reference types and appropriate values for value types (e.g. 0 for int, false for bool).