VB.NET XML 序列化继承对象的列表



我正在尝试序列化继承对象的列表。 当每个对象根据其真实类型声明时,我可以单独序列化每个对象,但是当它是基本类型的列表时,序列化程序会感到困惑,因为它期望序列化"base"对象,但随后看到继承了"base"对象的不同对象。

关于如何轻松解决此问题的任何想法? 我已经读了很多书,但没有找到一种优雅的易于维护的方式来做到这一点。

正在尝试序列化:

        'Define a list of the common inherited base for all print elements.
        '   This allows all types of print elements to be added to one list and in the user defined order
        '   Order is important for the layer of objects when 'drawing' them on the canvas during the on print options
        <XmlArrayAttribute("ElementsList")>    'Tell the XML Seralizer this is a list
        Public Elements As New List(Of CardItemBase)        'XML Serializer does not like this becuase the elements in this list are not CardItemBase, they are that + stuff, and it does not know what to do with stuff

下面是继承基的两个项示例,如果声明为真实类型,这两个项都将序列化(即使在列表中(:

    Public Class TextString
        'Inherit the common properties for a card item
        Inherits CardItemBase
        'Vars to hold string info to use when printing
        Public StringToPrint As String = String.Empty
        Public XLocation As Single = 0
        Public YLocation As Single = 0
        'Font info (store values instead of a Pen since Pen requires dispose and also does not work with Xml Serializing)
        Public Font As String = Nothing
        Public FontSize As Integer = 0
        Public FontColor As System.Drawing.KnownColor = Drawing.KnownColor.Black 'Note, does NOT require dispose
        'Constructor to force users to pass in all info
        Public Sub New()    'Create an empty Sub New Overload for use with XML Serializer
        End Sub
        Public Sub New(ByVal CardSide As CardSideOptions, ByVal InputStringToPrint As String, ByVal TextFont As String, ByVal TextSize As Integer, ByVal TextColor As System.Drawing.KnownColor, ByVal InputXLocation As Single, ByVal InputYLocation As Single)
            'Set the inherited objects
            MyBase.New(CardSide:=CardSide)
            'Save passed in info
            StringToPrint = InputStringToPrint
            Font = TextFont
            FontSize = TextSize
            FontColor = TextColor
            XLocation = InputXLocation
            YLocation = InputYLocation
        End Sub
        ''' <summary>
        ''' Return the ture type of this object as DriverJob.PrintElementTypes even if the item is nested in a CardItemBase list.
        ''' </summary>
        <XmlIgnore()>
        Public Overrides ReadOnly Property MyType() As PrintElementTypes
            Get
                Return PrintElementTypes.Text
            End Get
        End Property
        <XmlIgnore()>
        Public Overrides ReadOnly Property ToString() As String
            Get
                Try
                    'Create a string that descipes this object
                    Dim ReturnStr As String = ""
                    'Concatinate a description of each element
                    ReturnStr += "X: " & XLocation.ToString() & ", Y: " & YLocation.ToString() & ", "
                    ReturnStr += Font & ", " & FontSize & ", "
                    ReturnStr += FontColor.ToString() & ", "
                    ReturnStr += "'" & StringToPrint & "'"
                    'Return the completed string.
                    Return ReturnStr
                Catch ex As Exception
                    'Just return the error string
                    Return ex.Message
                End Try
            End Get
        End Property
    End Class
    ''' <summary>
    ''' Sub class for passing images to print to the printing method.
    ''' </summary>
    Public Class Image
        'Inherit the common properties for a card item
        Inherits CardItemBase
        'Vars to hold image info to use when printing
        Public ImageFilePathToUse As String = ""
        Public XLocation As Single = 0
        Public YLocation As Single = 0
        Public Height As Single = 0
        Public Width As Single = 0
        'Constructor to force users to pass in all info
        Public Sub New()    'Create an empty Sub New Overload for use with XML Serializer
        End Sub
        Public Sub New(ByVal CardSide As CardSideOptions, ByVal InputImageFilePathToUse As String, Optional ByVal InputXLocation As Single = 0, Optional ByVal InputYLocation As Single = 0, Optional ByVal InputHeight As Single = 0, Optional ByVal InputWidth As Single = 0)
            'Set the inherited objects
            MyBase.New(CardSide:=CardSide)
            'Save passed in info
            ImageFilePathToUse = InputImageFilePathToUse
            XLocation = InputXLocation
            YLocation = InputYLocation
            Height = InputHeight
            Width = InputWidth
        End Sub
        ''' <summary>
        ''' Return the ture type of this object as DriverJob.PrintElementTypes even if the item is nested in a CardItemBase list.
        ''' </summary>
        <XmlIgnore()>
        Public Overrides ReadOnly Property MyType() As PrintElementTypes
            Get
                Return PrintElementTypes.Image
            End Get
        End Property

            ''' <summary>
            ''' Creates a simple string description of the object
            ''' </summary>
            <XmlIgnore()>
            Public Overrides ReadOnly Property ToString() As String
                Get
                    Try
                        'Create a string that descipes this object
                        Dim ReturnStr As String = ""
                        'Concatinate a description of each element
                        ReturnStr += "X: " & XLocation.ToString() & ", Y: " & YLocation.ToString() & ", "
                        ReturnStr += "Height: " & Height.ToString() & ", Width: " & Width.ToString() & ", "
                        ReturnStr += ImageFilePathToUse
                        'Return the completed string.
                        Return ReturnStr
                    Catch ex As Exception
                        'Just return the error string
                        Return ex.Message
                    End Try
                End Get
            End Property
        End Class

经过几个小时的阅读和测试,我找到了一个适合我的解决方案。

在基类定义之上,可以使用 XML include 标记定义继承此基类的所有类型,以便序列化程序不会混淆。 在添加继承此基类的类时,这只增加了一个步骤,供我使用,我可以接受这一点。

这是我添加的代码行:

    'Class to hold common properties that may be needed for describing all card elements.  This is intented to be inherited
    <XmlInclude(GetType(TextString)), XmlInclude(GetType(Line)), XmlInclude(GetType(Rectangle)), XmlInclude(GetType(Image)), XmlInclude(GetType(PrintAndTopcoatBlocking)), XmlInclude(GetType(MagstripeSetup)), XmlInclude(GetType(SmartCardSetup))>
    Public MustInherit Class CardItemBase

最新更新