[英]XmlSerializer.Deserialize for a sub class (not an array)
因此,這讓我感到迷惑了幾個小時……我有一個看起來像這樣的xml結構:
<custom>
<priceLower>999999</priceLower>
<priceUpper>1000001</priceUpper>
<investment>true</investment>
<offtheplan>false</offtheplan>
<office>
<name>Melbourne Office</name>
<officeName>Head Office</officeName>
... more elements removed
</office>
</custom>
在我的應用程序中,我有一個Custom類,該類從上面的xml fine反序列化,定義如下:
[Serializable]
public class Custom : BaseEntity, IDataModel
{
[XmlElement("investment")]
public string Investment { get; set; }
[XmlElement("offtheplan")]
public string Offtheplan { get; set; }
[XmlElement("priceLower")]
public Decimal? PriceLower { get; set; }
[XmlElement("priceUpper")]
public Decimal? PriceUpper { get; set; }
[XmlElement("office")]
public Office Office { get; set; }
而我的Office對象定義如下:
[Serializable]
public class Office : BaseEntity, IDataModel
{
// temporary for debugging purposes:
private string _officeName;
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("officeName")]
public string OfficeName { get; set; }
[XmlElement("addressL1")]
public string Address1 { get; set; }
... more fields removed }
反序列化代碼(由助手類調用,並接收包含一個Custom對象的屬性對象,其中Custom對象包含一個Office對象)如下所示:
XmlSerializer s = null;
XmlAttributeOverrides attrOverrides = null;
/// if it's a Residential type, do it this way
if (typeof(T) == typeof(Residential))
{
attrOverrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes();
var attr = new XmlElementAttribute();
attr.ElementName = "office";
attr.Type = typeof(Office);
attrs.XmlElements.Add(attr);
attrOverrides.Add(typeof(Office), "office", attrs);
s = new XmlSerializer(typeof(T), attrOverrides);
}
s = attrOverrides == null
? new XmlSerializer(typeof(T))
: new XmlSerializer(typeof(T), attrOverrides);
var obj = s.Deserialize(stream);
return (T)obj;
所以...自定義對象完全反序列化..那里沒有問題。 但是辦公場所卻沒有,它的所有屬性始終以null表示。
有沒有一種方法可以確切地指定xml樹中的哪個元素包含Office對象的數據? 我曾嘗試將Office對象移動到與Custom(位於Property對象上)相同的位置,這確實更有意義,但是那也不起作用-我將其移動到Custom下以匹配xml結構。不能改變它,我找不到一種方法來指定應該從哪里獲取數據。
我在這里經歷過的另一個怪異之處……我添加了一個Serializer函數,該函數基本上從反序列化的對象創建一個新的XML文件。 我可以一直調試直到調用Serialize函數的位置-如果在發生序列化的對象之前先對其進行窺視,我可以看到Office對象僅包含空值。 但是序列化程序實際上將數據序列化到我的新XML文件中。
這是更奇怪的地方。 如果在調用Serialize()之前先查看對象,則它將始終序列化一個空元素。 但是,如果在序列化發生之前我不偷看那個對象,它將把數據序列化到那里。 我已經多次驗證了這一點-毫無疑問,這就是行為。 有人看過這樣的東西嗎? 框架在欺騙我嗎?
更新:
為了澄清起見,我的XML看起來像這樣(上面我只顯示了作用):
<propertyList>
<residential>
<custom>
<property1>
<office>
<officeName>
Office Name Here
</officeName>
</office>
</custom>
</residential>
</propertyList>
因此,那里有一些嵌套級別,這可能是我所要解決的問題,盡管我認為這更多的是VS問題。
反序列化器正在處理完整的XML,並反序列化為這樣的類結構:
住宅:屬性:BasePropertyType
自定義對象和辦公室對象都在住宅對象上實例化。 我嘗試將Office對象放到Custom對象上(以匹配xml結構),但這沒什么區別。 自定義正確序列化,Office不正確。
Visual Studio調試器是否完全有可能成為此處的紅色鯡魚。 如前所述,如果我調試並查看反序列化的對象,它將顯示為空,然后將其序列化回XML時,它將作為空。 但是,如果我不調試而只是不看對象就走了,那么所有屬性都會正確地序列化為XML。 當我無法調試正在發生的事情時,這將使繼續執行我需要進行的其余數據處理工作變得有些困難。 以前有人在VS中看到過這種行為嗎?
關於第一個問題, XmlSerializer
可以處理簡單的層次結構,因此在您的示例中XmlAttributeOverrides
是不必要的:
[Serializable]
[XmlRoot("custom")]
public class Custom
{
[XmlElement("investment")]
public string Investment { get; set; }
[XmlElement("offtheplan")]
public string Offtheplan { get; set; }
[XmlElement("priceLower")]
public Decimal? PriceLower { get; set; }
[XmlElement("priceUpper")]
public Decimal? PriceUpper { get; set; }
[XmlElement("office")]
public Office Office { get; set; }
}
[Serializable]
public class Office
{
// temporary for debugging purposes:
private string _officeName;
[XmlElement("name")]
public string Name { get; set; }
[XmlElement("officeName")]
public string OfficeName { get; set; }
[XmlElement("addressL1")]
public string Address1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
string xml = @"<custom>
<priceLower>999999</priceLower>
<priceUpper>1000001</priceUpper>
<investment>true</investment>
<offtheplan>false</offtheplan>
<office>
<name>Melbourne Office</name>
<officeName>Head Office</officeName>
</office>
</custom>";
XmlSerializer s = new XmlSerializer(typeof(Custom));
// Works fine without this
//XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
//var attrs = new XmlAttributes();
//var attr = new XmlElementAttribute();
//attr.ElementName = "office";
//attr.Type = typeof(Office);
//attrs.XmlElements.Add(attr);
//attrOverrides.Add(typeof(Office), "office", attrs);
//s = new XmlSerializer(typeof(Custom), attrOverrides);
using (StringReader reader = new StringReader(xml))
{
Custom c = (Custom)s.Deserialize(reader);
}
}
}
啊哈哈哈哈...我真是個蠢貨! 有一個同事陪伴着我,我們發現我做的事情確實很愚蠢,即:
public string ToString()
{
Name = null;
OfficeName = null;
Address1 = null;
Address2 = null;
City = null;
State = null;
Postcode = null;
Phone = null;
Banner = null;
Logo = null;
StringBuilder sb = new StringBuilder();
sb.Append(String.Format("Name:{0} / OfficeName: {1} / Address1: {2} / Address2: {3} / City: {4} / State: {5} / Postcode: {6} / Phone: {7} / Banner: {8} / Logo: {9}",
Name, OfficeName, Address1, Address2, City, State, Postcode, Phone, Banner, Logo));
return sb.ToString();
}
因此,每次我在調試器中查看對象時,它都在調用我的ToString()覆蓋,然后覆蓋所有值。
我不覺得很討厭。 大聲笑
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.