Let's say i have two projects in Visual Studio. The Base project and a Derived project.
The base project contains a base class:
Public Class Car
Property Name As String
End Class
and a generic class for serializing
Public Class Seriallizer(Of T)
Function SerializeObjToString(obj As T) As String
Dim serializer As XmlSerializer
Dim memStream As New MemoryStream
Dim xmlWriter As New XmlTextWriter(memStream, Encoding.UTF8)
Try
serializer = New XmlSerializer(GetType(T))
serializer.Serialize(xmlWriter, obj)
Dim xml As String
xml = Encoding.UTF8.GetString(memStream.GetBuffer)
xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)))
xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1))
Return xml
Catch e As Exception
MsgBox($"Error writing data to string: {e.Message}")
Finally
xmlWriter.Close()
memStream.Close()
xmlWriter = Nothing
serializer = Nothing
memStream = Nothing
End Try
Return ""
End Function
Now i have derived class "SpecialCar" in my second project.
Public Class SpecialCar
Inherits Car
Sub New()
MyBase.New
End Sub
Property VentorName As String
End Class
My project with the derived class has a reference to the base class project. When i now want to serialize the derived class i am getting an error:
Dim spezicalCar As New SpecialCar
Dim serializer As New Seriallizer(Of Car)
Dim str As String = serializer.SerializeObjToString(spezicalCar)
Error:
The type Derived.SpecialCar was not expected.
Use the XmlInclude or SoapInclude attribute to specify types that are not
known statically
I know, i can use the XMLInclude attribute but this does not work in this case, as the base class project does not know about the derived class project. In other SO posts i read something about providing a xml namespace to classes but i don't know how to do that. How can i serialize my derived class to an XML?
After doing a day of research i found a solution for my question.
First you need to write your own serializer (implementing the IXmlSerializable interface) class (should be gerneric, that you can use it for all abstract (Base/MustInherit)) classes. The following SO and codeproject.com links helped me to solve the task:
XML Serialization and Inherited Types
https://www.codeproject.com/Articles/8644/XmlSerializer-and-not-expected-Inherited-Types
In both links you are going to find a similar solution. Be aware, in the codeproject link you have to look in the comment section for the generic solution.
So here is my final generic serializer class, which you can place in the project with the base class, or in an dedicated project and add a reference in the base class to the dedicated project.
Unfortunately i had to wrap the base class in another class to use the custom serializer.
Call the serialzer like this:
You can also use it on lists of derived class objects:
EDIT 06.03.2024 I had an issue on reading the xml. For some reason the written type name was not found on reading. So i made a couple of changes in the code above. Now the assembly name and the type name are written in two xml attributes.