asp.net 如何使用DataContractSerializer反序列化由XmlSerializer序列化的对象?

mwg9r5ms  于 2022-11-19  发布在  .NET
关注(0)|答案(1)|浏览(152)

我在由XmlSerializer序列化的字符串中有一个序列化对象。我希望使用DataContractSerializer对其进行反序列化。
此代码生成一个空对象:

Dim Enc As New UTF8Encoding
Using Stream As New MemoryStream(Enc.GetBytes(rec.XML))
    Dim xtr As New XmlTextReader(Stream)
    Dim Formatter As New DataContractSerializer(GetType(SMTPSettings))
    smtp = Formatter.ReadObject(xtr, False)
End Using

字符串如下:

<?xml version="1.0"?>
<SMTPSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Host>mail.clubcompete.com</Host>
  <Port>26</Port>
  <UserName>outgoing@clubcompete.com</UserName>
  <Password>xxxxxxxxx</Password>
  <UseSSL>false</UseSSL>
  <TestEmailAddress>al@xxxxx-micro.com</TestEmailAddress>
</SMTPSettings>

如何使用DataContractSerializer反序列化字符串?我无法使用XmlSerializer,因为它会在我的服务器临时文件夹中创建DLL,并且Web主机不允许这样做。

rqmkfv5c

rqmkfv5c1#

你没有显示你的类SMTPSettings,所以我猜它看起来像这样:

Public Class SMTPSettings
    Public Property Host As String
    Public Property Port As Integer
    Public Property UserName As String
    Public Property Password As String
    Public Property UseSSL As String
    Public Property TestEmailAddress As String
End Class

如果您希望使用DataContractSerializer将问题中显示的XML反序列化为此类,则需要记住与XmlSerializer的以下区别:

  1. DataContractSerializer不支持XML属性(除了命名空间属性和特殊属性,例如xsi:type)。请参阅here以进行确认。
    幸运的是,XML不包含这样的属性。
  2. DataContractSerializer不支持序列化没有外部容器元素的集合。
    幸运的是,您的XML不包含没有外部容器的重复元素,因此这不适用。
    1.默认命名空间的推断方式不同。XmlSerializer假定类型在空XML命名空间中序列化,除非应用了XmlRootAttribute.Namespace之类的属性。DataContractSerializer假定类型在默认情况下在非空XML命名空间中序列化,特别是http://schemas.datacontract.org/2004/07/Clr.Namespace。有关确认信息,请参见数据协定命名空间。
    由于您的XML不在任何命名空间中,因此您需要将data contract attrtibutes套用至您的型别,以指定空的命名空间。
    1.元素必须排序。XmlSerializer允许元素以任何顺序排列,但DataContractSerializer要求元素以特定顺序排列。有关详细信息,请参见Data Member Order。如果未使用数据协定属性指定顺序,则数据协定序列化程序假定元素应按字母顺序进行序列化。
    由于XML元素不是按字母顺序排列的,因此需要再次使用数据协定属性来指定所需的顺序。
    将所有这些放在一起,可以使用以下版本的SMTPSettings来反序列化该XML示例:
<DataContract(Name:="SMTPSettings", [Namespace]:="")>
Public Class SMTPSettings
    <DataMember(Name:="Host", Order:=1)>
    Public Property Host As String
    <DataMember(Name:="Port", Order:=2)>
    Public Property Port As Integer
    <DataMember(Name:="UserName", Order:=3)>
    Public Property UserName As String
    <DataMember(Name:="Password", Order:=4)>
    Public Property Password As String
    <DataMember(Name:="UseSSL", Order:=5)>
    Public Property UseSSL As String
    <DataMember(Name:="TestEmailAddress", Order:=6)>
    Public Property TestEmailAddress As String
End Class

演示小提琴#1(在c#中)here
考虑到DataContractSerializer的所有限制,您可以考虑将类加载到LINQ to XMLXElement中,然后手动填充SMTPSettings,如下所示:

Dim xml = XElement.Parse(xmlString)
Dim smtp = New SMTPSettings With { _
    .Host = xml.Element("Host"), 
    .Port = xml.Element("Port"),
    .UserName = xml.Element("UserName"),
    .Password = xml.Element("Password"),
    .UseSSL = xml.Element("UseSSL"),
    .TestEmailAddress = xml.Element("TestEmailAddress")
}

这完全避免了对元素顺序的繁琐。
演示小提琴#2

相关问题