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