Serialization

Developer
Oct 8, 2010 at 1:12 AM

Why not used the built in XML or DataContract attributes?

Developer
Oct 29, 2010 at 2:29 AM

I didn't see this until just now.  The xml serialization that we have now was designed by Darrel Brown in order to support de-serializing extensible content from an interface.  The goal is that someone can mark their properties on a new kind of layer with the DotSpatial Serialize attribute, and it opts in to serializing that property without someone having to write a custom method body explicitly handling the serialization and deserialization from and to xml, which would require a lot of work on everyone's part.  If you use the built in attributes, I think you need to write code on the object itself that supports its custom serialization.  I have just recently modified the code to be more tolerant of version updates.  I don't know that much about DataContracts, and I doubt that they even existed back when Darrel wrote our Serialization code =).  Anyway, I'm always open for making things work better.  Currently if you try to serialize something really exotic, the reflection based code may not handle it exactly right.  If you'd like to pitch a convincing argument for something new that I probably don't understand just yet, then I'd love to hear more.

Ted

 

Developer
Oct 29, 2010 at 2:29 PM

I’m sure this is way too low-tech for the DS developer crowd, and may not be anything near what you’re looking for, but I use the pattern exampled below quite a bit. It actually handles versioning quite well. If a field exists in the serialized data, but the corresponding variable does not exist in class definition it does not care. If the field corresponding to a class variable does not exist in the serialized data, the default value of the variable is used. You do need to write the short SaveToXML and CreateFromXML methods on the top level object (but only on the top level object) you are (de)serializing…

 The first tag is not necessary, it just controls the name of the root element.

    [XmlRoot(ElementName = "EventData")]
    public class VertexCommitted
    {
        public bool CancelState = false;
        public Point3D Point;
        public bool KnownGood = false;
        public void SaveToXML(string filename)
        {
            StreamWriter sw = new StreamWriter(filename);
            XmlSerializer xs = new XmlSerializer(typeof(VertexCommitted));
            xs.Serialize(sw, this);
            sw.Close();
        }
        public static VertexCommitted CreateFromXML(string filename)
        {
            FileStream fs = new FileStream(filename, FileMode.Open);
            XmlSerializer x = new XmlSerializer(typeof(VertexCommitted));
            VertexCommitted retVal = (VertexCommitted)x.Deserialize(fs);
            fs.Close();
            return retVal;
        }
    }

Developer
Oct 29, 2010 at 4:05 PM

I like the use of the XmlAttributes for serialization,
I you want more control, you Implement IXmlSerializable (notes here http://river.sdsc.edu/wiki/XmlSerialization%20in%20Dot%20Net.ashx)

The modern versioned way is DataContracts and DataContract Serialiation
 

On Fri, Oct 29, 2010 at 6:29 AM, kellison <notifications@codeplex.com> wrote:

From: kellison

I’m sure this is way too low-tech for the DS developer crowd, and may not be anything near what you’re looking for, but I use the pattern exampled below quite a bit. It actually handles versioning quite well. If a field exists in the serialized data, but the corresponding variable does not exist in class definition it does not care. If the field corresponding to a class variable does not exist in the serialized data, the default value of the variable is used. You do need to write the short SaveToXML and CreateFromXML methods on the top level object (but only on the top level object) you are (de)serializing…

The first tag is not necessary, it just controls the name of the root element.

    [XmlRoot(ElementName = "EventData")]
    public class VertexCommitted
    {
        public bool CancelState = false;
        public Point3D Point;
        public bool KnownGood = false;
        public void SaveToXML(string filename)
        {
            StreamWriter sw = new StreamWriter(filename);
            XmlSerializer xs = new XmlSerializer(typeof(VertexCommitted));
            xs.Serialize(sw, this);
            sw.Close();
        }
        public static VertexCommitted CreateFromXML(string filename)
        {
            FileStream fs = new FileStream(filename, FileMode.Open);
            XmlSerializer x = new XmlSerializer(typeof(VertexCommitted));
            VertexCommitted retVal = (VertexCommitted)x.Deserialize(fs);
            fs.Close();
            return retVal;
        }
    }

Read the full discussion online.

To add a post to this discussion, reply to this email (DotSpatial@discussions.codeplex.com)

To start a new discussion for this project, email DotSpatial@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Developer
Oct 29, 2010 at 5:25 PM

Kyle, I think you are at the starting point where I was about 2 years ago before Darrel (a more experienced programmer from very early MapWindow history) offered to take time out from his day job and help with the project.  The method you describe is perfectly adequate as long as you don't use interfaces, and tightly control typing for each collection item.  It is a bit labor intensive, since every class has to manually handle their own serialization methods, but that isn't my major concern.  The problem is that in order to deserialize your VertexCommitted class, you first must know that you are working with a VertexCommitted class so that you can access the proper CreateFromXML() method.  Now imagine this scenario.  Polygon Symbolizers are made up of a set of patterns.  However, the pattern involved can be any object that implements IPattern.  Having each IPattern implement SaveToXML() is very extensible because, hey, the sky is the limit if you allow people to handle their own xml when serializing to a file.  They could put absolutely anything they think they need in there.  The problem is coming back from the XML.  In addition to having custom XML handling, the XML file would have to provide the data type context to work with.  In fact the data type might come from a library that is not even in a DotSpatial core library.  It might be in BobsBin.dll.  So even if I have all the correctly serialized properties so that if I  used a BobsClass to run CreateFromXML, how do I know I need a Bob's Class, and presuming I know I need it, how do I know where to get it?  In addition, this puts the burden of supporting this complexity on every user-developer implementing their own implementation of anything more complicated than an IPattern, or that used interface members itself.

We felt that if we could offload this sophistication from the standard implementer and reduce it to an opt-in tag, then that would be ideal.  Also, to prevent a lot of duplication, you will notice that in our xml files, a type is only stored in its assembly qualified name format once, and they are nicely grouped up at the top.  From that point on, the referencing in the xml is human readable.  Recently I put in additional checks so that if the version number doesn't match with what has been serialized it searches for a matching assembly without caring about version.

I have little or no experience with DataContracts, though they may be an option here.  It depends on how smart the serialization tools are that work with DataContract members are.  However, we should wait until HydroDesktop is 4.0 before relying on a serialization technique specified in 4.0 for saving and loading maps.  The thing with the XMLAttributes and DataContract attributes is that we can always add those too!  Then we could benefit from the run-time extensibility within framework, but other users that wanted to serialize symbology items under more controlled circumstances could do so using more conventional serialization systems.

Anyway, I don't know if that clarifies things, and I can't say I fully investigated the serialization options at the time, or know the advanced details of supporting extensibility within conventional xml, I can only tell you some basic reasoning behind what we did.  I had only started a very preliminary investigation and was basically at the point where Kyle is now when Darrell took over, and I think he did a pretty good job at solving the problem, but as time moves on, new mechanisms might offer even greater versatility, so I'm open to ideas.

Ted