簡體   English   中英

DataContract 序列化程序不反序列化為沒有容器元素的重復 XML 元素的列表

[英]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解決了相同的問題:

在 XML 中反序列化為沒有容器元素的 List

要反序列化 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

  • 在 VS 菜單中,單擊項目
  • 選擇添加參考...
  • 單擊程序集
  • 檢查System.Runtime.Serialization
  • 點擊確定

以下代碼中使用了以下 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM