VB.NET XML 序列化继承对象列表 [英] VB.NET XML Serialize a List of Inherited Objects
问题描述
我正在尝试序列化继承对象的列表.当根据其真实类型声明每个对象时,我可以单独序列化每个对象,但是当它是基本类型的列表时,序列化程序会感到困惑,因为它期望序列化基本"对象,但随后会看到继承了基本"的不同对象对象.
有关如何轻松解决此问题的任何想法?我已经阅读了大量内容,但还没有找到一种优雅且易于维护的方式来做到这一点.
尝试序列化:
<块引用> '为所有打印元素定义一个公共继承基础的列表.' 这允许将所有类型的打印元素以用户定义的顺序添加到一个列表中' 在打印选项期间在画布上绘制"对象时,顺序对于对象层很重要<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屋!