我正在尝试序列化我的代码。
当我使用XmlElement ASP.Net设置类成员的Order属性时,我在这一行上得到了例外;
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
例外是;
不一致的排序:如果在类的一个成员上使用,所有类似粒子的成员都需要'Order'属性,请在类成员'_hotelId'上使用XmlElement,XmlAnyElement或XmlArray自定义属性显式设置'Order'。
代码是:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
StreamReader responsereader = new StreamReader(response.GetResponseStream());
var responsedata = responsereader.ReadToEnd();
xmldoc = (XmlDocument)JsonConvert.DeserializeXmlNode(responsedata);
xmldoc.Save(@"C:\New folder\myfile.xml");
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add("hotelId");
dt.Columns.Add("name");
dt.Columns.Add("address1");
dt.Columns.Add("address2");
dt.Columns.Add("city");
dt.Columns.Add("postalCode");
dt.Columns.Add("countryCode");
dr = dt.NewRow();
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
Stream reader = new FileStream(@"C:\New folder\myfile.xml", FileMode.Open);
HotelListResponse htype = (HotelListResponse)serializer.Deserialize(reader);
dt.ReadXml(@"C:\New folder\myfile.xml");
foreach(hoteltype ht in htype.hotel){
GridView1.DataSource = dt;
GridView1.DataBind();
}
//responsereader.Close();
//request.GetResponse().Close();
}
}
catch (WebException ex)
{
if (ex.Response == null)
throw new NullReferenceException("WebException response");
throw ex;
}
}
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRoot("HotelListResponse")]
public class HotelListResponse
{
[System.Xml.Serialization.XmlElementAttribute("hotel")]
public hoteltype[] hotel;
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] Items {
get {
return this.hotel;
}
set {
this.hotel = value;
}
}
}
[Serializable]
[XmlType("hoteltype")]
public class hoteltype
{
hoteltype(){}
public int _hotelId;
public string _name;
public string _address1;
public string _address2;
public string _city;
public int _postalCode;
public string _countryCode;
[XmlElement]
public hoteltype[] htype;
[System.Xml.Serialization.XmlElement(Order=1)]
public int hotelId
{
get {
return _hotelId;
}
set{
_hotelId = value;
}
}
[System.Xml.Serialization.XmlElement(Order=2)]
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[System.Xml.Serialization.XmlElement(Order=3)]
public string address1
{
get
{
return _address1;
}
set
{
_address1 = value;
}
}
[System.Xml.Serialization.XmlElement(Order=4)]
public string address2
{
get
{
return _address2;
}
set
{
_address2 = value;
}
}
[System.Xml.Serialization.XmlElement(Order=5)]
public string city
{
get
{
return _city;
}
set
{
_city = value;
}
}
[System.Xml.Serialization.XmlElement(Order=6)]
public int postalCode
{
get
{
return _postalCode;
}
set
{
_postalCode = value;
}
}
[System.Xml.Serialization.XmlElement(Order=7)]
public string countryCode
{
get
{
return _countryCode;
}
set
{
_countryCode = value;
}
}
}
答案 0 :(得分:2)
如异常中所述,只要使用Order=xx
,就必须对类中的所有可序列化属性和字段进行排序。但是,_hotelId
似乎可能是一个私人支持领域。由于XmlSerializer
也会序列化公共字段,因此这可能是无意的。如果_hotelId
确实必须公开,但您不希望序列化,那么您可以使用XmlIgnore
。
我猜你的课可能看起来像:
[System.SerializableAttribute()]
public partial class HotelListResponse
{
[System.Xml.Serialization.XmlElement(Order = 0)]
public string SomeOrderedField
{
get;
set;
}
// ** Problem may be here
// Because the field is public, XmlSerializer will try to serialize this
public int _hotelId;
[System.Xml.Serialization.XmlElement(Order = 1)]
public int HotelId
{
get
{
return _hotelId;
}
set
{
_hotelId = value;
}
}
修改是的,这正是问题
将您的支持字段设为私有 - 这就是您拥有公共属性访问者的原因。
public int _hotelId; => private int _hotelId;
public string _name; => private string _name;
等
修改强>
[XmlElement(Order=0)]
public hoteltype[] htype;
我也会同时将其更改为某个属性。如果您使用的是.NET 3.5或更高版本,请使用自动支持字段。
[XmlElement(Order=0)]
public hoteltype[] htype
{
get;
set;
}
修改强>
如果您系统地应用了上述内容,那么您的可序列化类应如下所示:
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlRoot("HotelListResponse")]
public class HotelListResponse
{
// This is bad practice - never make a backing field public
//[System.Xml.Serialization.XmlElementAttribute("hotel")]
//public hoteltype[] hotel;
// Use the >= .Net 3.5 automatic properties - this way you don't need
// the backing field at all, which will prevent confusion over
// 'what gets serialized'
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] Items
{
get;
set;
}
}
[Serializable]
[XmlType("hoteltype")]
public class hoteltype
{
public hoteltype() { }
[System.Xml.Serialization.XmlElement(Order = 0)]
public hoteltype[] htype
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 1)]
public int hotelId
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 2)]
public string name
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 3)]
public string address1
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 4)]
public string address2
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 5)]
public string city
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 6)]
public int postalCode
{
get;
set;
}
[System.Xml.Serialization.XmlElement(Order = 7)]
public string countryCode
{
get;
set;
}
}
通过序列化/反序列化循环测试上述内容,如下所示:
XmlSerializer serializer = new XmlSerializer(typeof(HotelListResponse));
HotelListResponse X = new HotelListResponse();
X.Items = new hoteltype[2];
X.Items[0] = new hoteltype();
X.Items[0].address1 = "address1";
X.Items[1] = new hoteltype();
X.Items[1].address1 = "address2";
using (Stream writer = new FileStream(@"C:\temp\myfile.xml", FileMode.Create))
{
serializer.Serialize(writer, X);
writer.Flush();
}
Stream reader = new FileStream(@"C:\temp\myfile.xml", FileMode.Open);
HotelListResponse htype = (HotelListResponse)serializer.Deserialize(reader);
以下文件反序列化:
<?xml version="1.0"?>
<HotelListResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<hotelId>0</hotelId>
<address1>address1</address1>
<postalCode>0</postalCode>
</Items>
<Items>
<hotelId>0</hotelId>
<address1>address2</address1>
<postalCode>0</postalCode>
</Items>
</HotelListResponse>