【发布时间】:2013-08-21 18:51:45
【问题描述】:
我有一个 RESTful WCF 服务,我正在尝试向其发送任务列表。我在其他问题上发现你必须封装列表,我已经完成了,序列化看起来很顺利。
序列化列表产生的 XML 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<MobileRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TaskRequests xmlns="MyNameSpace">
<MobileTask>
<TaskArgs xsi:type="GetUser">
<Password>test</Password>
<UserName>t</UserName>
</TaskArgs>
<TaskID>1</TaskID>
<TaskType>GetUser</TaskType>
</MobileTask>
<MobileTask>
<TaskArgs xsi:type="GetUser">
<Password>test</Password>
<UserName>t2</UserName>
</TaskArgs>
<TaskID>2</TaskID>
<TaskType>GetUser</TaskType>
</MobileTask>
</TaskRequests>
</MobileRequest>
所以MobileRequest 类有一个属性,它是MobileTask 对象的列表。 MobileRequest 类的代码非常简单,如下所示:
<Serializable(), DataContract(Name:="MobileRequest", [Namespace]:="MyNameSpace")> _
Public Class MobileRequest
<XmlArray()> <DataMember(Name:="TaskRequests")> _
Public TaskRequests As List(Of MobileTask) = New List(Of MobileTask)
Public Sub New()
Me.TaskRequests = New List(Of MobileTask)
End Sub
End Class
MobileTask 类如下所示:
<Serializable(), DataContract(Name:="MobileTask", [Namespace]:="MyNamespace"), _
KnownType(GetType(Obj.GetUser)), XmlInclude(GetType(Obj.GetUser))> _
Public Class MobileTask
Public Enum TypesOfTasks As Integer
Unknown = 0
GetUser = 1
End Enum
<DataMember(Name:="TaskID")> _
Public TaskID As Integer
<DataMember(Name:="TaskType")> _
Public TaskType As TypesOfTasks
<DataMember(Name:="TaskArgs")> _
Public TaskArgs As Object
End Class
TaskArgs 的类型根据 TaskType 而变化。我为 TaskArgs 可能是的每种可能类型都包含了一个 XMLInclude 和 KnownType 标记。 (这可能有点矫枉过正,但是当序列化的某些东西不起作用并且还没有尝试清理它时,我就这样做了)
我在我的测试应用程序中用来尝试反序列化 XML 的代码是:
Using logg As New System.IO.MemoryStream()
Using sw As New System.IO.StreamWriter(logg)
sw.Write(txtSource.Text)
sw.Flush()
If logg.Length > 0 Then
Using reader As New System.IO.StreamReader(logg)
logg.Position = 0
Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(SMS_VendorObj.MobileRequest))
Dim results = ser.Deserialize(logg)
End Using
End If
End Using
End Using
这是来自一个简单的 winform 设置,它允许我粘贴 XML,因此 txtSource 只是一个文本框,我将我从序列化中获得的 XML 放入其中。
在运行测试应用程序时,我可以逐步执行上述反序列化代码,在 Dim results = ser.Deserialize(logg) 行之后 results 是正确的类型,但 MobileTask 列表不包含任何项目。
是我在类文件中遗漏了什么,还是我尝试反序列化列表的方式有问题?
如果我错过了重要的代码,请告诉我,我会更新任何需要的内容。我还删掉了多余的部分,所以我可能在不知不觉中剪掉了太多。
编辑:
GetUser 类:
<Serializable(), DataContract([Namespace]:="MyNamespace")> _
Public Class GetUser
<DataMember(Name:="UserName")> _
Public UserName As String
<DataMember(Name:="Password")> _
Public Password As String
End Class
编辑#2:
在处理了反序列化程序可能抛出的错误后,我发现反序列化过程在第 21 行位置 3 上抛出了一个UnknownNode 异常,然后是一个UnknownElement 异常。详细信息表明预期的元素是“:TaskRequests”。
【问题讨论】:
-
抱歉,没有注意到您已经有 XmlInclude。你能显示类型 Obj.GetUser 的定义吗?
-
@BartoszKP 请参考编辑。
-
您是否尝试过将
XmlInclude属性(KnownType在这里无关,因为它指的是DataContractSerializer)到属性TaskArgs? -
@BartoszKP 您能否将您的建议应用于我发布的课程的答案?我尝试只是简单地将标签拖放到
DataMember标签之后,环境根本不喜欢这样,所以我不确定你的意思。
标签: xml vb.net serialization