|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionAbout 3 months ago, I was asked to work out a program running on Pocket PC with .Net Compact FrameWork. It is a program drawing rooms and calculating the geometrical parameters and exporting them to XML file. The program itself , should be able to save the rooms to files and load from them. Compact FrameWork 2.0 doesn't provide Binary Serialization. And XML Serialization is just too simple to handle what I need: I have to deal with a complex topology of object model. Room A may be associated to Room B, and Room B to Room C, Room C to Room A, it makes a circle finally, just like this: So, I need a way to serialize such an object model to XML. Fortunately, I had worked out something in my spare time. I call it "xmlable", just like "Serializable" in Binary Serialization. Using the codeI will introduce Alex Fr's DrawTools to show you how this has been done. First, include IXmlabe.cs and Xmlable.cs to your project. Derive the classes you want to serialize from interface IXmlable, and declare an attribute Xmlable for it, and implement 2 methods of IXmlable: FromXml and ToXml using Xmlable;
using System.Xml;
namespace DrawTools
{
[Xmlable("DrawObject", IsUnique = false)]
abstract class DrawObject : IXmlable
{
public DrawObject(){/*...*/} // Xmlable need a constructor without parameter.
public virtual void FromXml(XmlElement xmlEle, IXmlContext cnt)
{
//base.FromXml(xmlEle,cnt); //the derived classes should call parent class's FromXml
color = Color.Black;
try { color = Color.FromArgb(Int32.Parse(xmlEle.GetAttribute("color"))); }
catch (Exception) { }
penWidth = 1;
try { penWidth = Int32.Parse(xmlEle.GetAttribute("penWidth")); }
catch (Exception) { }
name = xmlEle.GetAttribute("name");
XmlElement assoEle = xmlEle["associate"];
if(null != assoEle)
{
objAsso = cnt.FromXml(assoEle.FirstChild as XmlElement) as DrawObject;
}
}
public virtual void ToXml(XmlElement xmlEle, IXmlContext cnt)
{
//base.ToXml(xmlEle,cnt); //the derived classes should call parent class's ToXml
XmlToolkit.SetAttribute(xmlEle, "color", color.ToArgb().ToString());
XmlToolkit.SetAttribute(xmlEle, "penWidth", penWidth.ToString());
XmlToolkit.SetAttribute(xmlEle, "name", name);
XmlElement assoEle = cnt.Document.CreateElement("associate");
XmlElement objEle = cnt.ToXml(objAsso);
if (null != objEle)
assoEle.AppendChild(objEle);
xmlEle.AppendChild(assoEle);
}
} [Xmlable("TagName", IsUnique = true)] In order to make DrawTools "Xmlable", the five classes : DrawObject, DrawLine, DrawPolygon, DrawRectangle, DrawEllipse and GraphicsList was modified. GraphicsList is the container who contains DrawObject, its implement of IXmlable is like: public virtual void FromXml(XmlElement xmlEle, IXmlContext cnt)
{
graphicsList.Clear();
foreach (XmlElement objEle in xmlEle)
{
DrawObject obj = cnt.FromXml(objEle) as DrawObject;
System.Diagnostics.Debug.Assert(null != obj);
if (null != obj)
{
graphicsList.Add(obj);
}
}
}
public virtual void ToXml(XmlElement xmlEle, IXmlContext cnt)
{
foreach (DrawObject obj in graphicsList)
{
XmlElement objEle = cnt.ToXml(obj);
if (null != objEle)
xmlEle.AppendChild(objEle);
}
} To save the document of DrawTools, just add some code in MainForm, like this: Save private void saveAsXMLToolStripMenuItem_Click(object sender, EventArgs e)
{
if (dlgSave.ShowDialog() != DialogResult.OK)
return ;
XmlDocument doc = new XmlDocument();
IXmlFormatter formatter = FepXmlableFactory.CreateXmlFormatter();
IXmlContext cnt = FepXmlableFactory.CreateXmlContext(formatter, doc);
XmlElement ele = cnt.ToXml(this.drawArea.GraphicsList);
doc.AppendChild(ele);
XmlDeclaration xmldecl;
xmldecl = doc.CreateXmlDeclaration("1.0", null, null);
doc.InsertBefore(xmldecl, doc.DocumentElement);
doc.Save(dlgSave.FileName);
}
Load private void loadFromXMLToolStripMenuItem_Click(object sender, EventArgs e)
{
if (dlgOpen.ShowDialog() != DialogResult.OK)
return;
XmlDocument doc = new XmlDocument();
doc.Load(dlgOpen.FileName);
IXmlFormatter formatter = FepXmlableFactory.CreateXmlFormatter();
IXmlContext cnt = FepXmlableFactory.CreateXmlContext(formatter, doc);
GraphicsList graphList = cnt.FromXml(doc.DocumentElement) as GraphicsList;
if(null == graphList)
throw new System.IO.IOException(dlgOpen.FileName + " is not a valid file.");
this.drawArea.GraphicsList = graphList;
this.drawArea.Invalidate();
}
Hope this will help...If you are confused by what i have written above. Just download the project, run it, draw something, right click on them, set their properties and make them associate to each other. Go to menu "File->Save As XML","File->Load From XML", and open the saved file with text editors to have a look. I haven't done much test after I add Xmlable to DrawTools. Let's just focus on how objects be serialized to XML.
|
|||||||||||||||||||||||||||||||||||