VB.NET XML 序列化继承对象列表 [英] VB.NET XML Serialize a List of Inherited Objects

查看:27
本文介绍了VB.NET XML 序列化继承对象列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

有关如何轻松解决此问题的任何想法?我已经阅读了大量内容,但还没有找到一种优雅且易于维护的方式来做到这一点.

尝试序列化:

<块引用>

 '为所有打印元素定义一个公共继承基础的列表.' 这允许将所有类型的打印元素以用户定义的顺序添加到一个列表中' 在打印选项期间在画布上绘制"对象时,顺序对于对象层很重要<XmlArrayAttribute("ElementsList")>'告诉 XML Seralizer 这是一个列表Public Elements As New List(Of CardItemBase) 'XML Serializer 不喜欢这个,因为这个列表中的元素不是 CardItemBase,它们是那个 + 的东西,它不知道如何处理这些东西

以下是继承基类的两个项目示例,如果声明为它们的真实类型,它们都会序列化(即使在列表中).:

<块引用>

 公共类 TextString'继承卡片项目的公共属性继承 CardItemBase'保存打印时使用的字符串信息的变量Public StringToPrint As String = String.Empty公共 XLocation 作为单个 = 0公共 YLocation 为 Single = 0'字体信息(存储值而不是 Pen,因为 Pen 需要处理并且也不适用于 Xml 序列化)公共字体作为字符串 = 无公共字体大小为整数 = 0Public FontColor As System.Drawing.KnownColor = Drawing.KnownColor.Black '注意,不需要处理'强制用户传递所有信息的构造函数Public Sub New() '创建一个空的 Sub New Overload 以与 XML Serializer 一起使用结束子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)'设置继承对象MyBase.New(CardSide:=CardSide)'保存传入的信息StringToPrint = InputStringToPrint字体 = 文本字体字体大小 = 文本大小字体颜色 = 文本颜色XLocation = 输入 XLocationYLocation = InputYLocation结束子''' <总结>''' 将此对象的真实类型返回为 DriverJob.PrintElementTypes,即使该项目嵌套在 CardItemBase 列表中.''' </summary><XmlIgnore()>Public 将 ReadOnly 属性 MyType() 覆盖为 PrintElementTypes得到返回 PrintElementTypes.Text结束获取最终财产<XmlIgnore()>公共覆盖只读属性 ToString() 作为字符串得到尝试'创建一个描述这个对象的字符串Dim ReturnStr As String = ""'连接每个元素的描述ReturnStr += "X: " &XLocation.ToString() &", Y: " &YLocation.ToString() &"、"ReturnStr += 字体 &", " &字体大小"、"ReturnStr += FontColor.ToString() &"、"ReturnStr += "'" &StringToPrint &'"'返回完成的字符串.返回 ReturnStrCatch ex 作为例外'只返回错误字符串返回前消息结束尝试结束获取最终财产结束类''' <总结>''' 用于将要打印的图像传递给打印方法的子类.''' </summary>公开课图片'继承卡片项目的公共属性继承 CardItemBase'保存打印时使用的图像信息的变量Public ImageFilePathToUse As String = ""公共 XLocation 作为单个 = 0公共 YLocation 为 Single = 0公共高度为单身= 0公共宽度为单个 = 0'强制用户传递所有信息的构造函数Public Sub New() '创建一个空的 Sub New Overload 以与 XML Serializer 一起使用结束子Public Sub New(ByVal CardSide As CardSideOptions,ByVal InputImageFilePathToUse As String,可选ByVal InputXLocation As Single = 0,可选ByVal InputYLocation As Single = 0,可选ByVal InputHeight As Single = 0,可选ByVal InputWidth As Single = 0)'设置继承对象MyBase.New(CardSide:=CardSide)'保存传入的信息ImageFilePathToUse = InputImageFilePathToUseXLocation = 输入 XLocationYLocation = InputYLocation高度 = 输入高度宽度 = 输入宽度结束子''' <总结>''' 将此对象的真实类型返回为 DriverJob.PrintElementTypes,即使该项目嵌套在 CardItemBase 列表中.''' </summary><XmlIgnore()>Public 将 ReadOnly 属性 MyType() 覆盖为 PrintElementTypes得到返回 PrintElementTypes.Image结束获取最终财产''' <总结>''' 创建对象的简单字符串描述''' </summary><XmlIgnore()>公共覆盖只读属性 ToString() 作为字符串得到尝试'创建一个描述这个对象的字符串Dim ReturnStr As String = ""'连接每个元素的描述ReturnStr += "X: " &XLocation.ToString() &", Y: " &YLocation.ToString() &"、"ReturnStr += "高度:" &Height.ToString() &", 宽度: " &Width.ToString() &"、"ReturnStr += ImageFilePathToUse'返回完成的字符串.返回 ReturnStrCatch ex 作为例外'只返回错误字符串返回前消息结束尝试结束获取最终财产结束类

解决方案

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

在基类定义之上,可以使用 XML 包含标记定义所有继承该基类的类型,这样序列化程序就不会被混淆.在添加继承此基类的类时,这仅增加了一个步骤,对于我的使用,我可以忍受.

这是我添加的代码行:

<块引用>

 '类来保存描述所有卡片元素可能需要的通用属性.这是打算继承<XmlInclude(GetType(TextString)), XmlInclude(GetType(Line)), XmlInclude(GetType(Rectangle)), XmlInclude(GetType(Image)), XmlInclude(GetType(PrintAndTopcoatBlocking)), XmlInclude(GetType(MagstripeSetup)),XmlInclude(GetType(SmartCardSetup))>公共 MustInherit 类 CardItemBase

I'm trying to serialize a list of inherited objects. I can serialize each object individually when its declared according to its true type, but when its a list of the base type the serializer gets confused because its expecting to serialize a "base" object but then see different objects that had inherited the "base" object.

Any ideas on how to easily solve this? I've done a bunch of reading and have not found an elegant easy to maintain way to do this.

Trying to serialize:

        '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

Here are two examples of items that inherited the base, both of which will serialize (even in a list) if declared as their true type.:

    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

解决方案

After a few more hours of reading and testing I found a solution that will work for me.

Above the base class definition the XML include tag can be used define all the types that inherited this base class so the serializer won't be confused. This adds only one step to do when adding classes that inherit this base class, for my use I can live with this.

Here is line of code I added:

    '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

这篇关于VB.NET XML 序列化继承对象列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆