As usual I bumped into the strange phenom of font serialization by a mistake. The class I was working on needed the System.Drawing.Font for styling and when trying to serialize the property directly I got the infamous line: “System.Drawing.Font cannot be serialized because it does not have a parameterless constructor.”
A simple test yielded, it’s true. There’s no System.Drawing.Font().
The class was already working, changing the interface of a working class is a very bad idea. Yet in order to serialize it I had to. So I did the minimum required, add properties. Unlike deleting, this approach allows (most of) the code to work after recompiling, or in the case of reflection without a change (see note later on).
How to Serialize the Font
1. Change it to a read-only property. Easy, remove the “set” part.
note: if you really need to leave it just put [System.Xml.Serialization.XmlIgnore] on the property, thus the serializer won't parse it.
2. Split it into a few properties:
private System.Drawing.Font l_Font = new System.Drawing.Font("Times New Roman", 24);
public System.Drawing.Font Font
{
get
{
return l_Font;
}
} public string FontName
{
get
{
return l_Font.Name;
}
set
{
l_Font = new System.Drawing.Font(value, l_Font.Size, l_Font.Style, l_Font.Unit, l_Font.GdiCharSet, l_Font.GdiVerticalFont);
}
}
public float FontSize
{
get
{
return l_Font.Size;
}
set
{
l_Font = new System.Drawing.Font(l_Font.Name, value, l_Font.Style, l_Font.Unit, l_Font.GdiCharSet, l_Font.GdiVerticalFont);
}
}
public System.Drawing.FontStyle FontStyle
{
get
{
return Font.Style;
}
set
{
l_Font = new System.Drawing.Font(l_Font.Name, l_Font.Size, value, l_Font.Unit, l_Font.GdiCharSet, l_Font.GdiVerticalFont);
}
}
public System.Drawing.GraphicsUnit Unit
{
get
{
return l_Font.Unit;
}
set
{
l_Font = new System.Drawing.Font(l_Font.Name, l_Font.Size, l_Font.Style, value, l_Font.GdiCharSet, l_Font.GdiVerticalFont);
}
}
public byte CharSet
{
get
{
return l_Font.GdiCharSet;
}
set
{
l_Font = new System.Drawing.Font(l_Font.Name, l_Font.Size, l_Font.Style, l_Font.Unit, value, l_Font.GdiVerticalFont);
}
}
public bool Vertical
{
get
{
return l_Font.GdiVerticalFont;
}
set
{
l_Font = new System.Drawing.Font(l_Font.Name, l_Font.Size, l_Font.Style, l_Font.Unit, l_Font.GdiCharSet, value);
}
}
Nice hack, but works well.
P.S. Just before submitting I remembered to add this 2 nice (actually supreme useful) methods to the class:
public static void Serialize(string Filename, SerializableFont obj)
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(SerializableFont));
System.IO.StreamWriter sw = new System.IO.StreamWriter(Filename);
x.Serialize(sw, obj);
sw.Close();
}
public static SerializableFont DeSerialize(string Filename)
{
SerializableFont res;
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(SerializableFont));
System.IO.StreamReader sr = new System.IO.StreamReader(Filename);
res = (SerializableFont)x.Deserialize(sr);
sr.Close();
return res;
}
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(SerializableFont));
System.IO.StreamWriter sw = new System.IO.StreamWriter(Filename);
x.Serialize(sw, obj);
sw.Close();
}
public static SerializableFont DeSerialize(string Filename)
{
SerializableFont res;
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(SerializableFont));
System.IO.StreamReader sr = new System.IO.StreamReader(Filename);
res = (SerializableFont)x.Deserialize(sr);
sr.Close();
return res;
}
The serialization methods that saves the rewriting of serialize... in every location needed in the code.
No comments:
Post a Comment