473,320 Members | 2,161 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,320 developers and data experts.

How To : Apply XmlSerialization with an Interface

179 100+
This is a little bit more of an advanced topic for serialization. For those who don't know what XML serialization is, then this probably isn't for you just yet. For those that do, you may have come across the problem of serializing an interface, something that you simply can't do using the standard XmlSerialization techniques. This articles looks at how to do that, although it might be a little length. Lets take the following problem:

Expand|Select|Wrap|Line Numbers
  1.  public interface IPoint
  2.     {
  3.         double X;
  4.         double Y;
  5.         double DistanceBetween(IPoint point);
  6.     }
  7.  
  8.     public class Point2Dimensional : IPoint
  9.     {
  10.         public double X { get; protected set; }
  11.         public double Y { get; protected set; }
  12.         public virtual double DistanceBetween(IPoint point) { ... }
  13.     }
  14.  
  15.     public class Point3Dimensional : Point2Dimensional
  16.     {
  17.         public double Z { get; protected set; }
  18.         public override double  DistanceBetween(IPoint point) { ... }
  19.     }
  20.  
If we now have a class that has an IPoint.

Expand|Select|Wrap|Line Numbers
  1.     public class PointHolder
  2.     {
  3.         public IPoint Point { get; set; }
  4.     }
  5.  
This now means that we cannot deserialize the PointHolder class using standard serialization, because the serializer isn't clever enough to figure out the type it should be deserializing. However, it is possible to do so manually, using some custom serialization.

Firstly we want to make sure both our points can serialize / deserialize themselves. So we change our code slightly. I've ommitted the parameterless constructors, obviously you'll need to add those in.

1) Make the IPoint interface implement IXmlSerializable

Expand|Select|Wrap|Line Numbers
  1.  public interface IPoint : IXmlSerializable
  2.     {
  3.         double X;
  4.         double Y;
  5.         double DistanceBetween(IPoint point);
  6.     }
  7.  
2) Make the Point2Dimensional and Point3Dimensional implement the IXmlSerializable interface like so. I've just done the 2Dimensional class, obviously the other just adds Z to the list of things to serialize/deserialize.

Expand|Select|Wrap|Line Numbers
  1.    public class Point2Dimensional : IPoint
  2.     {
  3.         public double X { get; protected set; }
  4.         public double Y { get; protected set; }
  5.         public virtual double DistanceBetween(IPoint point) { ... }
  6.  
  7.         public System.Xml.Schema.XmlSchema GetSchema()
  8.         {
  9.             return null;
  10.         }
  11.  
  12.         public void ReadXml(System.Xml.XmlReader reader)
  13.         {
  14.             this.X = Convert.ToDouble(reader.GetAttribute("X"));
  15.             this.Y = Convert.ToDouble(reader.GetAttribute("Y"));
  16.         }
  17.  
  18.         public void WriteXml(System.Xml.XmlWriter writer)
  19.         {
  20.             writer.WriteAttributeString("X", this.X.ToString());
  21.             writer.WriteAttributeString("Y", this.Y.ToString());
  22.         }
  23.     }
  24.  
We now need to make our PointHolder implement IXmlSerializable too. This uses some extension methods which do the hardwork which we'll see in a minute. Again you'll need your parameterless constructor in there too.

Expand|Select|Wrap|Line Numbers
  1.     public class PointHolder : IXmlSerializable
  2.     {
  3.         public IPoint Point { get; set; }
  4.  
  5.         public System.Xml.Schema.XmlSchema GetSchema()
  6.         {
  7.             return null;
  8.         }
  9.  
  10.         public void ReadXml(System.Xml.XmlReader reader)
  11.         {
  12.             this.Point = reader.ReadXmlSerializableElement<IPoint>("Point");
  13.         }
  14.  
  15.         public void WriteXml(System.Xml.XmlWriter writer)
  16.         {
  17.             writer.SaveXmlSerialiableElement("Point", this.Point);
  18.         }
  19.     }
  20.  
What we do here, is basically pass in an element name, and either save or assign our Point property. Now lets take a look at the extension methods defined somewhere in a static class.

Expand|Select|Wrap|Line Numbers
  1. public static void SaveXmlSerialiableElement<T>(this XmlWriter writer, String elementName, T element) where T : IXmlSerializable
  2.         {
  3.             writer.WriteStartElement(elementName);
  4.             writer.WriteAttributeString("TYPE", element.GetType().ToString());
  5.             element.WriteXml(writer);
  6.             writer.WriteEndElement();
  7.         }
  8.  
What's going on here? Well we write a new element with the given name, we then save the full type and namespace of that element, call through to the WriteXml on the element itself, then write the end tag. So the XML will look something like:

<Point>
<Point3Dimensional TYPE="TestApp.Point3Dimensional" x="0", y="0", z="0">
</Point>

Not too difficult. Reading is where things get interesting. There's a couple of methods that I won't go into that you'll need, I'm sure you can figure them out. The code is here:

Expand|Select|Wrap|Line Numbers
  1.      public static void ReadToElement(this XmlReader reader, String element)
  2.         {
  3.             reader.ReadToNextNode();
  4.             while (reader.Name != element)
  5.             {
  6.                 reader.ReadToNextNode();
  7.             }
  8.         }
  9.  
  10.         public static void ReadToNextNode(this XmlReader reader)
  11.         {
  12.             // Read the current item to throw it away
  13.             reader.Read();
  14.  
  15.             // Keep on reading till we have read all the whitespace
  16.             while (reader.NodeType == XmlNodeType.Whitespace)
  17.             {
  18.                 reader.Read();
  19.             }
  20.         }
  21.  
The part that is really useful however is:

Expand|Select|Wrap|Line Numbers
  1.   public static T ReadXmlSerializableElement<T>(this XmlReader reader, String elementName) where T : IXmlSerializable
  2.         {
  3.             reader.ReadToElement(elementName);
  4.  
  5.             Type elementType = Type.GetType(reader.GetAttribute("TYPE"));
  6.             T element = (T)Activator.CreateInstance(elementType);
  7.             element.ReadXml(reader);
  8.             return element;
  9.         }
  10.  
What this does, is firstly locates the element of interest. Then we read out the type of the element and create a new instance of it. We can then call through to the ReadXml on the element to initalize all it's members and return it.

This then means we can use XmlSerialization on our PointHolder regardless of the type of IPoint that it is storing within the Point property.
Jul 6 '09 #1
0 3923

Sign in to post your reply or Sign up for a free account.

Similar topics

0
by: Omkar Singh | last post by:
When I serialize my class using XmlSerialization.serialize, it make a lot of reference in the output document. Is there any way to off XmlSerialiation class to make references.
0
by: Omkar Singh | last post by:
I am using XmlSerialization and XmlDeserialization for making soap Body part. Then I am making sopa-header and other part of soap envelope manually. At last joining all part to get complete soap...
0
by: Omkar Singh | last post by:
I have a problem while using XmlSerialization. XmlSerializaion creates a lot of 'href' and namespaces while serializing a complex object. Can we control serialization to stop href and namespaces. ...
2
by: STom | last post by:
I have just started reading up on XMLSerialization and still do not understand the practical use of this technology. For example, if I have to know the class type on the client and on the web...
0
by: A programmer desperatly needing help! | last post by:
I use the xmlserialization on asp.net pages and on previous machines it never gave a problem. But now i somethings get a: Timed out waiting for a program to execute. The command being executed was...
4
by: pfrisbie | last post by:
I am developing a Web Services interface with C# and our partner is using Java (Axis 1.1). They require me to include xsi:types in the SOAP Messages I send them. For example: <Partner...
3
by: LW | last post by:
Hi! I am getting the following error message for my fairly simple web service. I have classes and have two DataSets that reference the same classes. The error is: The XML element named...
1
by: Frank | last post by:
Hi, Let's say I have a file named myFile.xml Within that file I have blocks of data which I'd like to add at different times during the day. e.g. <LogEntry>
0
by: =?Utf-8?B?R2FyeQ==?= | last post by:
I have Line, Rect, and Ellipse classes derived from IShape interface, and am using the generic list, List<IShape>, to store a bunch of objects. When I used XMLSerializer object to serialize this...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.