This is a continuation of this post regarding binary serialization. This time around, we are focused on XML Serialization, that is serializing an object to an XML document. That is, taking an in-memory instance of a class and “formatting” it as XML. Why would we do this? Simply to store the object somewhere (file, column in a database, etc…) or to transport the object (HTTP, TCP Socket, etc…). So, serialization is necessary whenever you need to send an object to a web service or save it to a text file, etc…
There are several different ways to accomplish XML Serialization. In some cases, it makes sense to hand code the solution, generally referred to as custom serialization. That might include writing ToXml/FromXml routines and carefully controlling the contents of the XML. The .Net Framework provides several easily implemented solutions. However; some of them can be rather resource intensive so watch that.
The System.Xml.Serialization namespace is required for the following code.
To serialize:
Dim _xmlSerializer As XmlSerializer
Dim _xmlStream As StringWriter = New StringWriter
_xmlSerializer = New XmlSerializer(pObject.GetType)
_xmlSerializer.Serialize(_xmlStream, _object)
Return _xmlStream.GetStringBuilder.ToString
To deserialize:
Dim _xmlSerializer As XmlSerializer
Dim _object As Object
Dim _textReader As StringReader
_textReader = New StringReader(_serializedObject)
_xmlSerializer = New XmlSerializer(GetType(“SerializedObject”))
_object = _xmlSerializer.Deserialize(_textReader)
Easy enough and well documented. However; the actual implementation of this is a little vague. Obviously, every situation is different and we developers must be smart enough to work within these various situations. I see many developers that are willing to drive head first into brick walls, backup, and drive straight into it again. In my opinion, this is one of the things that differentiates a good developer from the masses of folks that claim to be developers.
In my specific case, I had a service that was to receive any type of serialize object (via message queue) and had to figure out what to do with that object (i.e. send it to listeners via TCP Socket, send to message queues, etc…). I needed a flexible solution and the hardcoding of an object type in the code above was a problem. I elected to store the type in the message header and the serialized object (string) in the message body. Note that the length of the string (serialized entity) is included as a carry over from binary serialization. So, my code looks like this:
Public Shared Function SerializeXML(ByVal pObject As Object, _
ByRef pHeader As String) As String
Dim _xmlSerializer As XmlSerializer
Dim _xmlStream As StringWriter = New StringWriter
Dim _xmlSerializerNamespace As XmlSerializerNamespaces
‘ This simply clears the XMLNS attribute from the XML document
‘ Used when serializing objects.
_xmlSerializerNamespace = New XmlSerializerNamespaces
_xmlSerializerNamespace.Add(“”, “”)
_xmlSerializer = New XmlSerializer(pObject.GetType)
_xmlSerializer.Serialize(_xmlStream, pObject, _xmlSerializerNamespace)
Dim xmlSize As Integer = _xmlStream.GetStringBuilder.Length
‘ Send assembly name with type so proxy can more easily find the class
pHeader = String.Format(“${0}|{1}|”, xmlSize, _
String.Concat(pObject.GetType.ToString(), “, “, _
pObject.GetType.Assembly.ToString.Substring( _
0, pObject.GetType.Assembly.ToString.IndexOf(“,”))))
Return _xmlStream.GetStringBuilder.ToString
_xmlStream.Close()
_xmlStream = Nothing
End Function
And the Deserialize code is:
Public Shared Function DeserializeXML(ByVal pHeader As String, _
ByVal pObjString As String) As Object
Dim _xmlSerializer As XmlSerializer
Dim _header() As String = pHeader.Split(“|”)
Dim _xmlSize As String = _header(0)
Dim _objectType As String = _header(1)
Dim _assembly As String = _header(2)
Dim _object As Object
‘ Handle situations where object is coming from the CF
If _objectType.IndexOf(“BOLCF”) > -1 Then
_objectType = _objectType.Replace(“BOLCF”, “BOL”)
End If
‘ Create a new StringReader to pass to Deserialization routine
Dim _textReader As StringReader
_textReader = New StringReader(pObjString)
Dim _type As Type = Type.GetType(_objectType)
If IsNothing(_type) Then
If _objectType.IndexOf(“,”) > -1 Then
_objectType = _objectType.Substring(0, _objectType.IndexOf(“,”))
_type = Type.GetType(_objectType)
End If
End If
If IsNothing(_type) Then
‘ Cannot deserialize…
_object = Nothing
Else
_xmlSerializer = New XmlSerializer(_type)
_object = _xmlSerializer.Deserialize(_textReader)
End If
_xmlSerializer = Nothing
Return _object
End Function
Leave a Reply