Hello,
I'm writing a TypeConverter for a class which inherits arraylist, but
deserializing it always results in an arraylist, which causes an
InvalidCastException. If anyone can point out what I'm doing wrong here,
I'd really appreciate it.
The class:
<TypeConverter(GetType(CXMLObjectListConverter)) > _
Public Class CXMLObjectList
Inherits ArrayList
#Region "Constants"
Private Const XML_ATTRIBUTE_Count As String = "Count"
Private Const XML_ATTRIBUTE_ClassName As String = "ClassName"
#End Region
#Region "New()"
Public Sub New()
MyBase.New()
End Sub
#End Region
#Region "New(ByVal RootElement As String)"
Public Sub New(ByVal RootElement As String)
MyBase.New()
mRootElement = RootElement
End Sub
#End Region
#Region "New(ByVal RootElement As String, ByVal TotalCount As Integer)"
Public Sub New(ByVal RootElement As String, ByVal TotalCount As
Integer)
MyBase.New()
mRootElement = RootElement
mTotalCount = TotalCount
End Sub
#End Region
#Region "New(ByVal xDoc As XmlDocument)"
Public Sub New(ByVal xDoc As XmlDocument)
Me.New(xDoc.ChildNodes(0))
RootElement = xDoc.ChildNodes(0).Value
End Sub
#End Region
#Region "New(ByVal xNode As XmlNode)"
Public Sub New(ByVal xNode As XmlNode)
Dim childValue As String
TotalCount = CInt(xNode.Attributes(XML_ATTRIBUTE_Count).Value)
For Each childNode As XmlNode In xNode.ChildNodes
If xNode.Item(childNode.Name).HasChildNodes Then
Dim myType As Type =
Type.GetType(childNode.Attributes(XML_ATTRIBUTE_Cl assName).Value)
Dim types(0) As Type
types(0) = GetType(XmlNode)
' Get the public instance constructor for the loaded type
Dim constructorInfoObj As ConstructorInfo = _
myType.GetConstructor(BindingFlags.Instance
Or _
BindingFlags.Public, Nothing, _
CallingConventions.HasThis, types, Nothing)
If Not (constructorInfoObj Is Nothing) Then
Dim parms(0) As Object
parms(0) = CType(childNode, XmlNode)
Me.Add(constructorInfoObj.Invoke(parms))
End If
End If
Next
End Sub
#End Region
#Region "Members"
Private mRootElement As String
Private mTotalCount As Integer
#End Region
#Region "Properties"
Public Property TotalCount() As Integer
Get
If mTotalCount = 0 Then
mTotalCount = Me.Count
End If
Return mTotalCount
End Get
Set(ByVal Value As Integer)
mTotalCount = Value
End Set
End Property
Public Property RootElement() As String
Get
Return mRootElement
End Get
Set(ByVal Value As String)
mRootElement = Value
End Set
End Property
#End Region
#Region "toXMLDocument"
Public Function toXMLDocument() As XmlDocument
Return toXMLDocument(Nothing)
End Function
Private Function toXMLDocument(ByVal objectList As ArrayList) As
XmlDocument
Dim xmlStream As New MemoryStream
Dim xml As New XmlTextWriter(xmlStream, Encoding.UTF8)
xml.WriteStartDocument()
xml.WriteStartElement(RootElement)
xml.WriteAttributeString(XML_ATTRIBUTE_Count, TotalCount.ToString)
If IsNothing(objectList) Then
objectList = Me
End If
For Each xObject As CXMLObject In objectList
xObject.toXML(xml)
Next
xml.WriteEndElement()
xml.WriteEndDocument()
xml.Flush()
xmlStream.Seek(0, SeekOrigin.Begin)
Dim xmldoc As New XmlDocument
xmldoc.Load(xmlStream)
Return xmldoc
End Function
#End Region
End Class
The TypeConverter:
Public Class CXMLObjectListConverter
Inherits TypeConverter
Public Overloads Overrides Function CanConvertFrom(ByVal context As
System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As
System.Type) As Boolean
If sourceType Is GetType(XmlDocument) OrElse sourceType Is
GetType(XmlNode) Then
Return True
End If
If sourceType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overloads Overrides Function ConvertFrom(ByVal context As
System.ComponentModel.ITypeDescriptorContext, ByVal culture As
System.Globalization.CultureInfo, ByVal value As Object) As Object
If TypeOf value Is XmlDocument OrElse value Is GetType(XmlNode)
Then
Return New CXMLObjectList(CType(value, XmlNode))
End If
If TypeOf value Is String Then
Dim xDoc As New XmlDocument
xDoc.LoadXml(CStr(value))
Return New CXMLObjectList(xDoc)
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overloads Overrides Function CanConvertTo(ByVal context As
System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As
System.Type) As Boolean
If destinationType Is GetType(XmlDocument) OrElse
destinationType Is GetType(XmlNode) Then
Return True
End If
If destinationType Is GetType(String) Then
Return True
End If
Return MyBase.CanConvertTo(context, destinationType)
End Function
Public Overloads Overrides Function ConvertTo(ByVal context As
System.ComponentModel.ITypeDescriptorContext, ByVal culture As
System.Globalization.CultureInfo, ByVal value As Object, ByVal
destinationType As System.Type) As Object
If destinationType Is GetType(XmlDocument) OrElse
destinationType Is GetType(XmlNode) Then
Return CType(value, CXMLObjectList).toXMLDocument
End If
If destinationType Is GetType(String) Then
Return CType(value, CXMLObjectList).toXMLDocument.ToString
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
The Code I'm using to test:
Dim list As New CXMLObjectList
Dim los As New LosFormatter
Dim sw As New StringWriter
los.Serialize(sw, list)
list = Nothing
list = los.Deserialize(sw.GetStringBuilder.ToString)
Thanks in advance,
-Eric