繁体   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