我有一个使用直接代码反序列化XML的难题,它似乎非常忠实地遵循msdn文档,但它没有产生预期的对象成员值:
给出以下类结构
[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中的值明确为&#39;时,ResultStatus属性设置为FALSE:
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值。
我犯了一个明显的错误,或者这是一个已知的问题?问题是反序列化代码,类定义还是XML?
答案 0 :(得分:1)
您遇到的问题是命名空间。在XML中,ResultStatus
行使用xmlns
属性标记了命名空间。因此,您需要在DataContract
中使用此命名空间。如果您将AddResult类更改为:
[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被正确读取。
编辑:
这是一个自包含的示例,显示正在读入系统的值以及所有填充正确的值。这包括对您在问题中遗漏的课程的最佳猜测。
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;
}
}