XML 反序列化谜题

XML deserialisation puzzle

我对使用直接代码反序列化 XML 感到困惑,这些代码似乎非常忠实地遵循 msdn 文档,但没有产生预期的对象成员值:

给定以下 class 结构

[DataContract(Namespace = "")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

[DataContract(Namespace = "")]
public class AddOrderResult : AddResult
{

    [DataMember()]
    public Order Order;
}

和以下 XML:

<AddOrderResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ErrorMessage i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService" />
  <Result i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService" />
  <ResultStatus xmlns="http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService">true</ResultStatus>
  <Order>
    <Kto>10025</Kto>
    <LIMSIdentifier>12345</LIMSIdentifier>
    <Matchcode>test order 1</Matchcode>
    <OfficeLineHandle>547864</OfficeLineHandle>
    <OverruleCreditCheck>true</OverruleCreditCheck>
  </Order>
</AddOrderResult

以下代码(其中 xmlResponse 是一个包含上述 XML 的 XDocument 对象)生成一个 AddOrderResult 对象,当 XML 显然是 'true':

     AddOrderResult res;
     using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse.ToString())))
    {
        stream.Position = 0;
        XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
        DataContractSerializer ser = new DataContractSerializer(typeof(AddOrderResult),new Type[] {typeof(AddResult)});
        res = (AddOrderResult)ser.ReadObject(reader,true);
        resultStatus = res.ResultStatus; //<-this should be true, but is actually false
    }

这种略有不同的方法具有相同的结果:

            AddOrderResult res;
            using (MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse.ToString())))
            {
                stream.Position = 0;
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
                XmlSerializer ser = new XmlSerializer(typeof(AddOrderResult),new Type[] {typeof(AddResult)});
                res = (AddOrderResult)ser.Deserialize(reader);
                resultStatus = res.ResultStatus; //<-this should be true, but is actually false
            }

在生成的反序列化 AddOrderResult 对象中,Order 属性(一个对象本身)具有所有正确的值;只有 xml 中的 ErrorMessage、Result 和 ResultStatus 值未正确反序列化。

我是犯了一个明显的错误,还是这是一个已知问题?问题出在反序列化代码、class 定义还是 XML 中?

您遇到的问题与命名空间有关。在您的 XML 中,ResultStatus 行使用 xmlns 属性标记有命名空间。因此,您需要在 DataContract 中使用此命名空间。如果您将 AddResult class 更改为:

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

您会发现 ResultStatus 被正确读取。

编辑:

这是一个独立的示例,显示了正在读入系统并正确填充的所有值。这包括对您在问题中遗漏的 classes 的最佳猜测。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;

namespace SO_AddOrder
{
    class Program
    {
        const string Xml = @"<AddOrderResult xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
  <ErrorMessage i:nil=""true"" xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"" />
  <Result i:nil=""true"" xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"" />
  <ResultStatus xmlns=""http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService"">true</ResultStatus>
  <Order>
    <Kto>10025</Kto>
    <LIMSIdentifier>12345</LIMSIdentifier>
    <Matchcode>test order 1</Matchcode>
    <OfficeLineHandle>547864</OfficeLineHandle>
    <OverruleCreditCheck>true</OverruleCreditCheck>
  </Order>
</AddOrderResult>";

        static void Main(string[] args)
        {
            AddOrderResult res;
            using (MemoryStream stream = new MemoryStream(Encoding.Default.GetBytes(Xml)))
            {
                stream.Position = 0;
                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
                DataContractSerializer ser = new DataContractSerializer(typeof(AddOrderResult), new Type[] { typeof(AddResult) });
                res = (AddOrderResult)ser.ReadObject(reader, true);
            }
            Console.WriteLine(res.ResultStatus);
        }
    }



    // Define other methods and classes here
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/appulsive.Intertek.LIMSService")]
public class AddResult
{
    [DataMember()]
    public string ErrorMessage;
    [DataMember()]
    public bool ResultStatus;
    [DataMember()]
    public string Result;
}

[DataContract(Namespace = "")]
public class AddOrderResult : AddResult
{

    [DataMember()]
    public Order Order;
}

[DataContract(Namespace = "")]
public class Order
{

    [DataMember()] 
    public int Kto;


    [DataMember()]
    public string LIMSIdentifier;

    [DataMember()]
    public string Matchcode;

    [DataMember()]
    public int OfficeLineHandle;

    [DataMember()]
    public bool OverruleCreditCheck;
}
}