I am trying to learn VB.NET and wanted to parse some classes into an XML structure, however, I am a bit confused as to how one class is nested into the other. I assumed I would have to instantiate each class and add an empty variable with the nested class as datatype within the main class but I keep getting the error in the title. The XML structure I am aiming for would look like:
<GType>
<dataModel>
<data key="Data1" value="10"/>
<data key="Data1" value="10"/>
...
</dataModel>
</GType>
It is the part inside the I am having trouble with defining. Here are the classes and functions I am trying to use.
Classes:
Partial Public Class GType
Private dataModelField() As dataModelType
<System.Xml.Serialization.XmlArrayItemAttribute("data", GetType(dataModelType), IsNullable:=False)>
Public Property dataModel() As dataModelType()
Get
Return Me.dataModelField
End Get
Set(value As dataModelType())
Me.dataModelField = value
End Set
End Property
...
End Class
Partial Public Class dataModelType
Private keyField As String
Private valueField As String
<System.Xml.Serialization.XmlAttributeAttribute()>
Public Property key() As String
Get
Return Me.keyField
End Get
Set(value As String)
Me.keyField = value
End Set
End Property
<System.Xml.Serialization.XmlAttributeAttribute()>
Public Property value() As String
Get
Return Me.valueField
End Get
Set(value As String)
Me.valueField = value
End Set
End Property
End Class
Function:
...
Dim retObj As GType = Nothing
If V6Assign IsNot Nothing Then
mainObj = New GType()
Dim assignValStr As String = V6Assign.Source.Value.ToLower.Trim
Dim assignVal As SByte = 0
SByte.TryParse(assignValStr, assignVal)
Dim dataModel As dataModelType = New dataModelType()
dataModel.key = "Data1"
dataModel.value = "10"
mainObj.dataModel = dataModel
Is this some scoping issue I am unaware of? Any suggestions on how to approach this?
CodePudding user response:
You are pretty close. In your code, you are making one dataModel
, but need a list of dataModel. Like this:
...
Dim retObj As GType = Nothing
If V6Assign IsNot Nothing Then
mainObj = New GType()
Dim assignValStr As String = V6Assign.Source.Value.ToLower.Trim
Dim assignVal As SByte = 0
SByte.TryParse(assignValStr, assignVal)
Dim dataModel As dataModelType = New dataModelType()
dataModel.key = "Data1"
dataModel.value = "10"
''This would assign one dataModel, but you need an array
'mainObj.dataModel = dataModel
Dim dataModels(0) as dataModelType 'array with one element, prob too small
dataModels(0) = dataModel
mainObj.dataModel = dataModels
Probably it would be better, in your class to have dataModelField as Array(of dataModelType)
, because it will auto-resize when you .Add
more dataModelType
elements.
CodePudding user response:
Using Auto-Implemented Properties, I created the following model:
Partial Public Class GType
<XmlArray("dataModel")>
<XmlArrayItem("data")>
Public Property DataModel As Data()
End Class
Partial Public Class Data
<XmlAttribute(AttributeName:="key")>
Public Property Key As String
<XmlAttribute(AttributeName:="value")>
Public Property Value As String
End Class
The trick is to provide a name for the array as well as for the array items.
I have this at the top of the vb file:
Imports System.IO
Imports System.Xml.Serialization
The Partial
keyword is not required for the following tests; however, you probably have another reason for it.
This serialization test...
Public Sub SerializationTest()
Dim serializer = New XmlSerializer(GetType(GType))
Dim root = New GType With {
.DataModel = {
New Data With {.Key = "Data1", .Value = "10"},
New Data With {.Key = "Data2", .Value = "20"}
}
}
Using writer = New StringWriter()
serializer.Serialize(writer, root)
Console.WriteLine(writer.ToString())
End Using
End Sub
... produces
<?xml version="1.0" encoding="utf-16"?>
<GType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<dataModel>
<data key="Data1" value="10" />
<data key="Data2" value="20" />
</dataModel>
</GType>
This deserialization test...
Public Sub DeserialzationTest()
Dim xml As String =
"<GType>
<dataModel>
<data key=""Data1"" value=""10""/>
<data key=""Data2"" value=""20""/>
</dataModel>
</GType>"
Dim serializer = New XmlSerializer(GetType(GType))
Using reader = New StringReader(xml)
Dim result = CType(serializer.Deserialize(reader), GType)
For Each d As Data In result.DataModel
Console.WriteLine($"{d.Key} = {d.Value}")
Next
End Using
End Sub
... prints:
Data1 = 10
Data2 = 20