Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

XML Serialization in Windows Phone 7 Tips and Tricks

0.00/5 (No votes)
13 Oct 2011 1  
Some tips how to handle serialization in Windows Phone 7

Introduction

Recently, I've been trying to serialize some complex classes and below you can find my tips on how to solve the errors on Windows Phone 7.

Using the Code

In the demo code, I've created Settings class that we will be trying to Serialize. Note that you need to have Windows Phone SDK 7.1 installed to run the project.

Settings class has two methods to simplify save and load operations.

public void Save()
    {
        IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
        IsolatedStorageFileStream stream = storage.CreateFile(AppSettingsFileName);

        XmlSerializer xml = new XmlSerializer(GetType());
        xml.Serialize(stream, this);

        stream.Close();
        stream.Dispose();
    }
public static Settings Load()
    {
        IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
        Settings tmpSettings;

        if (storage.FileExists(AppSettingsFileName))
        {
            IsolatedStorageFileStream stream = 
			storage.OpenFile(AppSettingsFileName, FileMode.Open);
            XmlSerializer xml = new XmlSerializer(typeof(Settings));

            tmpSettings = xml.Deserialize(stream) as Settings;

            stream.Close();
            stream.Dispose();
        }
        else
        {
            tmpSettings = new Settings();
        }

        return tmpSettings;
    }

As you can see, we use Standard XML Serialization offered by .NET Framework. (You need to add reference to System.XML.Serialization in new project.)

Problem 1 - Stream Opened in Save Method

Note that we didn't add any exception handling to the save code, so if serialization fails the stream will be left opened. Let's try to add new properties to the Settings class.

public Dictionary<string, int> SomeSettings { get; set; }
public int[] Array { get; set; }
public int[,] Array2D { get; set; }

If you now add Main Form to buttons to call save and load functions and run the program, you should see Exception during Save method.

There was an error reflecting type 'Serialization.Settings'.

The inner exception says that it couldn't serialize SomeSettings property. For now, we can mark it with [XmlIgnore] attribute and rerun the program. Save operation now should be successfully completed. But sometimes and this point, you get exception that says:

An error occurred while accessing IsolatedStorage. 
Windows phone 7 at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor

It's because stream is opened and hanging from the previous run of the program in emulator. Now you must restart emulator to fix this problem. To get rid of this error, you need to modify the code of Save/Load functions:

public void Save()
        {
            IsolatedStorageFile storage = 
		IsolatedStorageFile.GetUserStoreForApplication();
            IsolatedStorageFileStream stream = null;
            try
            {
                stream = storage.CreateFile(AppSettingsFileName);

                XmlSerializer xml = new XmlSerializer(GetType());
                xml.Serialize(stream, this);
            }
            catch (Exception ex)
            { }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                }
            }
        }
        public static Settings Load()
        {
            IsolatedStorageFile storage = 
		IsolatedStorageFile.GetUserStoreForApplication();
            Settings tmpSettings;

            if (storage.FileExists(AppSettingsFileName))
            {
                IsolatedStorageFileStream stream = null;
                try
                {
                    stream = storage.OpenFile(AppSettingsFileName, FileMode.Open);
                    XmlSerializer xml = new XmlSerializer(typeof(Settings));

                    tmpSettings = xml.Deserialize(stream) as Settings;
                }
                catch (Exception ex)
                {
                    tmpSettings = new Settings();
                }
                finally
                {
                    if (stream != null)
                    {
                        stream.Close();
                        stream.Dispose();
                    }
                }
            }
            else
            {
                tmpSettings = new Settings();
            }

            return tmpSettings;
        }

Problem 2 - Things You Can't Serialize

Let's add constructor to the settings class:

public Settings()
        {
            SomeSettings = new Dictionary<string, int>() 
			{ { "Code", 1 }, { "User", 2 } };
            Array = new int[] { 1, 23, 4 };
            Array2D = new int[,] { { 1, 2 }, { 3, 4 } };
        }

Now the serialization will fail because we try to serialize two dimensional array. You can solve this by replacing 2D array with List<int[]>.

You also cannot serialize Dictionary<P,Q>. Solving that is a bit harder. One option is to replace Dictionary by List<Pair> where Pair is:

public class Pair<t,q />
    {
        public T Key { get; set; }
        public Q Value { get; set; }

        public Pair() {}
        public Pair(T x, Q y)
        {
            Key = x;
            Value = y;
        }
    }

Other restrictions on class serialization:

  • Class must be public
  • Class must have default constructor
  • Only public members will be serialized
  • Properties must have both get/set public

Links

History

  • 1.0 - created 10/12/2011

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here