In C#, it is very easy to serialise your objects to and from XML.
//public type, so that the serialiser can use it:
public class UserSettings
{
//default constructor with no params, so that the serialiser can create it:
public UserSettings()
{
}
//public property:
public string Name
{
get { return name; }
set { name = value; }
}
}
using System.IO;
using System.Xml;
using System.Xml.Serialization;
...
UserSettings settings = new UserSettings();
//... populate the settings object
//now serialise settings to XML file:
string fileName = @"c:\my_usersettings.xml";
XmlSerializer xs = new XmlSerializer(typeof(UserSettings));
using(TextWriter tw = new StreamWriter(fileName))
{
xs.Serialize(tw, this);
tw.Close();
}
Problems
However, with more complex situations, which are fairly common, the XML serialisation can run into problems.
Hierarchies:
Some hierarchies will encounter a runtime error when the serialiser tries to navigate the hierarchy. This can happen:
Say you have a base class 'Base1' and two or more derived classes 'Derived1', 'Derived2' etc.
Then say you have a collection, which contains a mixture of the derived types:
List list = new List();
list.Add(new Derived1());
list.Add(new Derived2());
The serialiser cannot handle serialising such a collection.
Complex Type - Requires Custom Serialisation:
Obfuscation:
Some solutions
Hierarchies:
Custom Type - Requires custom serialisation:
There is an article on CodeProject, which uses a TypeConverter to serialise a BitMap (plus some other useful examples):
http://www.codeproject.com/KB/XML/xml_serializationasp.aspx
There is a CodeProject article here on implementing your own TypeConverter:
http://www.codeproject.com/KB/dotnet/BasicPropertyGrid.aspx
Obfuscation:
Use the Obfuscation attribute to switch off obfuscation for a particular type or member:
[Obfuscation(ApplyToMembers = true, Feature = "renaming", Exclude = true)]
public class ChangeDetection
{
...
...
public ChangeDetection()
{
}
//is serialized:
[Obfuscation(Exclude = true)]
[XmlAttribute("KeywordsEnabled")]
public bool KeywordsEnabled
{
get
{
return bKeywordsEnabled;
}
}
...
...
}
- just set the visibility to be public, for the types and members that you want serialised:
//public type, so that the serialiser can use it:
public class UserSettings
{
//default constructor with no params, so that the serialiser can create it:
public UserSettings()
{
}
//public property:
public string Name
{
get { return name; }
set { name = value; }
}
}
- then write code like this:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
...
UserSettings settings = new UserSettings();
//... populate the settings object
//now serialise settings to XML file:
string fileName = @"c:\my_usersettings.xml";
XmlSerializer xs = new XmlSerializer(typeof(UserSettings));
using(TextWriter tw = new StreamWriter(fileName))
{
xs.Serialize(tw, this);
tw.Close();
}
Problems
However, with more complex situations, which are fairly common, the XML serialisation can run into problems.
Hierarchies:
Some hierarchies will encounter a runtime error when the serialiser tries to navigate the hierarchy. This can happen:
- if there are circular references (for example, the typical parent-child two way reference that occurs in a Composite pattern)
Say you have a base class 'Base1' and two or more derived classes 'Derived1', 'Derived2' etc.
Then say you have a collection, which contains a mixture of the derived types:
List
list.Add(new Derived1());
list.Add(new Derived2());
The serialiser cannot handle serialising such a collection.
Complex Type - Requires Custom Serialisation:
- some complex types require custom serialisation (for example, serialising a bitmap to a mime type)
Obfuscation:
- if obfuscation is active (as the obfuscator will unpredictably abbreviate the type and member names, which of course will affect the XML)
Some solutions
Hierarchies:
- before serialisation, flatten your hierarchy into a list of nodes, which use a simple string key to refer to each other.
- after de-serialisation, restore your hierarchy, by using a hashtable populated with the simple string keys
Serialising a collection of base types
This seems to be a specific example of a more general problem, where if a public member is of a base type, then the serialiser cannot handle the case where the member refers to a derived type.
There is a good article here which provides a solution:
Custom Type - Requires custom serialisation:
There is an article on CodeProject, which uses a TypeConverter to serialise a BitMap (plus some other useful examples):
http://www.codeproject.com/KB/XML/xml_serializationasp.aspx
There is a CodeProject article here on implementing your own TypeConverter:
http://www.codeproject.com/KB/dotnet/BasicPropertyGrid.aspx
Obfuscation:
Use the Obfuscation attribute to switch off obfuscation for a particular type or member:
[Obfuscation(ApplyToMembers = true, Feature = "renaming", Exclude = true)]
public class ChangeDetection
{
...
...
public ChangeDetection()
{
}
//is serialized:
[Obfuscation(Exclude = true)]
[XmlAttribute("KeywordsEnabled")]
public bool KeywordsEnabled
{
get
{
return bKeywordsEnabled;
}
}
...
...
}
Comments
Post a Comment