Reputation: 168
I have a question regarding the serialization of a generic class.
Because I want to use a generic class for all my Configuration (which gets serialized as an XML) I have written the following class:
Imports System.Xml
Imports System.Xml.Serialization
Imports System.IO
Imports System.Reflection
Imports System.Reflection.Assembly
<Serializable()> _
Public Class GenericConfig(Of T)
Public Sub WriteToFile(ByVal FileName As String)
ConfigVersion = ProgrammVersion.ToString
Dim XmlFile As FileStream = New FileStream(FileName, FileMode.Create)
Dim serialize As XmlSerializer = New XmlSerializer(GetType(GenericConfig(Of T)), New Type() {GetType(GenericConfig(Of T))})
serialize.Serialize(XmlFile, Me)
XmlFile.Close()
End Sub
Public Shared Function ReadFromFile(ByVal FileName As String) As GenericConfig(Of T)
Dim XmlFile As FileStream = New FileStream(FileName, FileMode.Open)
Dim serialize As XmlSerializer = New XmlSerializer(GetType(GenericConfig(Of T)))
ReadFromFile = serialize.Deserialize(XmlFile)
XmlFile.Close()
Return ReadFromFile
End Function
Public Shared ReadOnly Property ConfigFileName() As String
Get
Return GetExecutingAssembly.Location.Substring(0, GetExecutingAssembly.Location.Length - 4) & ".Config.xml"
End Get
End Property
End Class
Public Class ToolConfig
Inherits GenericConfig(Of ToolConfig)
Public Property Key1 As String = "Value 1"
End Class
The problem I have is that I cannot serialize it because of the following error at line
serialize.Serialize(XmlFile, Me)
{"The type GenericConfigClass.ToolConfig was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
I have googled and found a lot of article which relate to that error if you use XMLSerializer on derived classes. I am not doing that here. I am using it on a generic class.
Is there a way other than creating an XML helper class like this fellow here: http://www.codeproject.com/Articles/35925/Generic-XML-Serialization-Methods
Thanks,
Wolfgang
Update:
This is how I call it (short example)
Imports System.IO
Public Class frmMain
Dim Config As ToolConfig
Private Sub btnConfigInit_Click(sender As Object, e As EventArgs) Handles btnConfigInit.Click
'----------------- read config file -----------------
If File.Exists(ToolConfig.ConfigFileName) Then
Config = ToolConfig.ReadFromFile(ToolConfig.ConfigFileName)
Else
Config = New ToolConfig
End If
Config.WriteToFile(ToolConfig.ConfigFileName)
MsgBox(Config.Key1)
End Sub
End Class
Upvotes: 4
Views: 3910
Reputation: 174299
Yes, you are using a derived class: ToolConfig
. Make it known via XmlInclude
and you should be fine:
Add <XmlInclude(GetType(ToolConfig))>
to GenericConfig
.
Another solution should be to simply use Me.GetType()
instead of GetType(GenericConfig(Of T))
when creating the XmlSerializer
instance:
Dim serialize As XmlSerializer = New XmlSerializer(Me.GetType())
To be able to successfully deserialize, you will have to make the shared ReadFromFile
method either an instance method or make it generic.
If you want to keep that deserializing method shared, you can do it like this:
Public Class GenericConfig ' <- No (Of T) here! But in the line below.
Public Shared Function ReadFromFile(Of T)(ByVal FileName As String) As T
Dim XmlFile As FileStream = New FileStream(FileName, FileMode.Open)
Dim serialize As XmlSerializer = New XmlSerializer(GetType(T))
ReadFromFile = serialize.Deserialize(XmlFile)
XmlFile.Close()
Return ReadFromFile
End Function
End Class
Usage:
GenericConfig.ReadFromFile(Of ToolConfig)(filename)
Upvotes: 1