Feb 10 2011

Simple Data Serialization on WP7

Category: MobileJoel Ivory Johnson @ 04:21

You've got a class that contains data that you want to be able to save and load in IsolatedStorage on Windows Phone 7.  How would you go about doing that? There is more than one way, but I wanted to share a generic solution for didactic purposes; I'm finding that many begininers like to start off with a single satisficing solution and brance off into specialized solutions later.  Let's say that you are starting off with a stereotypical Employee class. 

 

class Employee 
     public int EmployeeNumber { getset; } 
     public string Name { getset; } 
     public string Department { getset; } 

 

There are a couple of problems with this employee class that make it unsuitable for the type of serialization that will be used. First the class isn't marked as public. This is a requirement for the DataContract serializaer. Secondly the class needs to be marked as serializable and the properties to be serialized must be marked. We mark the class as serializable by giving it the [DataContract] attribute. Each property that needs to be serialized must be marked with the [DataMember] attribute.  When we apply these changes the class looks like the following. 

 

[DataContract] 
public class Employee  
{  
     [DataMember] 
     public int EmployeeNumber { getset; }  
     [DataMember] 
     public string Name { getset; }  
     [DataMember] 
     public string Department { getset; }  
}  

 

There's another requirement that the class already met that I didn't mention. The class needs to have a default constructor. Sicne we've not given this class a default constructor the runtime will provide one. Now that we have a serializable class we need a way to serialize it. The DataContractSerializer would be used to handle both serialization and deserialization of the class. In it's simplest form you only need to provide the type that the serializer will handle. So a serializaer could be created with the following code. 

 

DataContractSerializer mySerializer = new DataContractSerializer(typeof(Employee)); 

 

That serializer can be used to read or write your object to a stream such as a file stream, network stream, or memory stream. I've set forth to only save and read contents from a file stream. So I've made a generic class that contains most of the logic to do that. 

 

using System; 
using System.IO; 
using System.IO.IsolatedStorage; 
using System.Runtime.Serialization; 
 
 
public class DataSaver<MyDataType> 
    private const string TargetFolderName = "MyFolderName"
    private DataContractSerializer _mySerializer; 
    private IsolatedStorageFile _isoFile; 
    IsolatedStorageFile IsoFile 
    { 
        get 
        { 
            if (_isoFile == null
                _isoFile = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication(); 
            return _isoFile; 
        } 
    } 
 
    public DataSaver() 
    { 
        _mySerializer = new DataContractSerializer(typeof(MyDataType)); 
    } 
 
    public void SaveMyData(MyDataType sourceData, String targetFileName) 
    { 
        string TargetFileName = String.Format("{0}/{1}.dat", TargetFolderName, targetFileName); 
        if (!IsoFile.DirectoryExists(TargetFolderName)) 
            IsoFile.CreateDirectory(TargetFolderName); 
        try 
        { 
            using (var targetFile = IsoFile.CreateFile(TargetFileName)) 
            { 
                _mySerializer.WriteObject(targetFile, sourceData); 
            } 
        } 
        catch (Exception e) 
        { 
            IsoFile.DeleteFile(TargetFileName); 
        } 
 
 
    } 
 
    public MyDataType LoadMyData(string sourceName) 
    { 
        MyDataType retVal = default(MyDataType); 
        string TargetFileName = String.Format("{0}/{1}.dat", TargetFolderName, sourceName); 
        if (IsoFile.FileExists(TargetFileName)) 
            using (var sourceStream = IsoFile.OpenFile(TargetFileName, FileMode.Open)) 
            { 
                retVal = (MyDataType)_mySerializer.ReadObject(sourceStream); 
            } 
        return retVal; 
    } 
 

 

I've hard coded the folder name in which the data will be saved (feel free to save that). When using the class you only need to pass it the object to be saved and the name of the file that it will use. 

 

//declare instance 
DataSaver<Employee> myEmployeeDataSaver = new DataSaver<Employee>(); 
 
//read Usage 
var EmployeeData = myEmployeeDataSaver.LoadMyData("MyEmployeeDataFileName"); 
 
//save Usage 
myEmployeeDataSaver.SaveMyData(myEmployee,"MyEmployeeDataFileName"); 

 

That should be enough to get you started. I'm working on a much more complete explanation to be shared later. 

Tags: ,