[英]DataContract serializer not deserializing into a list repeating XML elements without container element
我們面臨的情況是DataContract
序列化程序(WCF 服務)沒有將沒有容器元素的重復 XML 元素反序列化到列表中; list 屬性以零元素結束。
我們擁有的數據合約:
[DataContract]
public class Requestor
{
[DataMember(IsRequired = true, Order = 0)]
public string RequestorRole;
[DataMember(IsRequired = true, Order = 1)]
public string RequestorGivenName;
[DataMember(IsRequired = true, Order = 2)]
public string RequestorSurName;
[DataMember(IsRequired = false, Order = 3)]
public List<RequestorIdentification> RequestorIdentification { get; set; }
}
[DataContract]
public class RequestorIdentification
{
[DataMember(IsRequired = true, Order = 0)]
public string IdentificationID;
[DataMember(IsRequired = true, Order = 1)]
public string IdentificationCategoryCode;
}
我們要反序列化的 XML:
<Requestor xmlns="http://schemas.datacontract.org/2004/07/Serialization"> <RequestorRole>Physicians</RequestorRole> <RequestorGivenName>Rich</RequestorGivenName> <RequestorSurName>Smith</RequestorSurName> <RequestorIdentification> <IdentificationID>AB1234567</IdentificationID> <IdentificationCategoryCode>DEA</IdentificationCategoryCode> </RequestorIdentification> <RequestorIdentification> <IdentificationID>0123456789</IdentificationID> <IdentificationCategoryCode>NPI</IdentificationCategoryCode> </RequestorIdentification> </Requestor>
我們如何使用DataContract
序列化程序解決問題?
到目前為止,我們還沒有找到讓它工作的方法,而且這個頁面https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/collection-types-in-data-contracts不是有很大幫助。
此問題中的XmlSerializer
解決了相同的問題:
要反序列化 OP 中顯示的 XML,可以使用XmlElement 。 但是,這需要使用XmlSerializer而不是DataContractSerializer進行序列化和反序列化。
根據這個帖子
DataContractSerializer 不支持 XmlSerializer 和 ASP.NET Web 服務使用的編程模型。 特別是,它不支持 XmlElementAttribute 和 XmlAttributeAttribute 等屬性。 若要啟用對此編程模型的支持,必須將 WCF 切換為使用 XmlSerializer 而不是 DataContractSerializer。
下面的代碼顯示了如何反序列化 OP 中顯示的 XML。
創建 Windows 窗體應用程序 (.NET Framework)
添加引用(System.Runtime.Serialization)
VS 2019
以下代碼中使用了以下 using 指令:
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
創建一個類(名稱:RequestorRequestorIdentification.cs)
[DataContract(Name = "RequestorIdentification")]
public class RequestorRequestorIdentification
{
[DataMember]
public string IdentificationID { get; set; }
[DataMember]
public string IdentificationCategoryCode { get; set; }
}
創建一個類(名稱:Requestor.cs)
[DataContract(Name ="Requestor")]
public class Requestor
{
[DataMember]
public string RequestorRole { get; set; }
[DataMember]
public string RequestorGivenName { get; set; }
[DataMember]
public string RequestorSurName { get; set; }
[XmlElement]
public List<RequestorRequestorIdentification> RequestorIdentification { get; set; } = new List<RequestorRequestorIdentification>();
}
注意:使用XmlElement需要使用XmlSerializer而不是DataContractSerializer進行序列化和反序列化。
創建一個類(名稱:HelperXml.cs)
public class HelperXml
{
public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
//usage: Requestor requestor = DeserializeXMLFileToObject<Requestor>(xmlFilename);
if (String.IsNullOrEmpty(xmlFilename))
throw new Exception("Error: xmlFilename is null or empty.");
return DeserializeXMLToObject<T>(File.ReadAllBytes(xmlFilename));
}
public static T DeserializeXMLToObject<T>(string xmlText)
{
//usage: Requestor requestor = DeserializeXMLToObject<Requestor>(xmlText);
//create new instance
using (System.IO.StringReader reader = new System.IO.StringReader(xmlText))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T), "http://schemas.datacontract.org/2004/07/Serialization");
return (T)serializer.Deserialize(reader);
}
}
public static T DeserializeXMLToObject<T>(byte[] xmlBytes)
{
//usage: Requestor requestor = DeserializeXMLToObject<Requestor>(File.ReadAllBytes(xmlFilename));
//create new instance of MemoryStream
using (MemoryStream ms = new MemoryStream(xmlBytes))
{
using (XmlTextReader reader = new XmlTextReader(ms))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T), "http://schemas.datacontract.org/2004/07/Serialization");
return (T)serializer.Deserialize(reader);
}
}
}
public static void SerializeObjectToXMLFile(object obj, string xmlFilename)
{
//Usage: Class1 myClass1 = new Class1();
//SerializeObjectToXMLFile(myClass1, xmlFilename);
if (String.IsNullOrEmpty(xmlFilename))
throw new Exception("Error: xmlFilename is null or empty.");
//Xml writer settings
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Encoding = Encoding.UTF8;
settings.Indent = true;
using (XmlWriter writer = XmlWriter.Create(xmlFilename, settings))
{
//specify namespaces
System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
ns.Add(string.Empty, "http://schemas.datacontract.org/2004/07/Serialization");
//create new instance
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType(), "http://schemas.datacontract.org/2004/07/Serialization");
//write to XML file
serializer.Serialize(writer, obj, ns);
}
}
}
用法(反序列化):
private Requestor _requestor = null;
...
//deserialize
//_requestor = HelperXml.DeserializeXMLFileToObject<Requestor>(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Test.xml"));
//_requestor = HelperXml.DeserializeXMLToObject<Requestor>(System.Text.Encoding.UTF8.GetBytes(xmlText));
_requestor = HelperXml.DeserializeXMLToObject<Requestor>(xmlText);
用法(序列化):
private Requestor _requestor = null;
...
//create new instance
_requestor = new Requestor();
_requestor.RequestorRole = "Physicians";
_requestor.RequestorGivenName = "Rich";
-requestor.RequestorSurName = "Smith";
_requestor.RequestorIdentification.Add(new RequestorRequestorIdentification() { IdentificationID = "AB1234567", IdentificationCategoryCode = "DEA" });
_requestor.RequestorIdentification.Add(new RequestorRequestorIdentification() { IdentificationID = "0123456789", IdentificationCategoryCode = "NPI" });
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "XML File (*.xml)|*.xml";
sfd.FileName = "Test.xml";
if (sfd.ShowDialog() == DialogResult.OK)
{
HelperXml.SerializeObjectToXMLFile(_requestor, sfd.FileName);
Debug.WriteLine($"Info: Saved to '{sfd.FileName}'");
}
}
其他資源:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.