所以这让我难以忍受了好几个小时......我有一个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中反序列化,定义如下:
[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 }
Deserialize代码(由辅助类调用,并接收包含A Custom对象的Property Object,其中包含一个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;
SO ... Custom对象完全反序列化..没有问题。但是办公室没有 - 所有它的属性总是以空的形式出现。
有没有办法准确指定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对象都在Residential对象上实例化。我已经尝试将Office对象放在Custom对象上(以匹配xml结构),但这没有任何区别。自定义序列化正确,Office没有。
Visual Studio调试器是否可能是红鲱鱼。正如我之前提到的,如果我调试并查看反序列化对象,它会将其显示为空,然后当我将其序列化回XML时,它会变为空。但是如果我不进行调试而只是在不查看对象的情况下单步执行,则所有属性都会正确地序列化到XML。当我无法调试那里正在发生的事情时,这使我很难继续前进并完成我需要的其余数据处理。有没有人在VS之前看到VS中的行为?
答案 0 :(得分:0)
关于您的第一个问题,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);
}
}
}
答案 1 :(得分:0)
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()覆盖,然后覆盖所有的值。
我不觉得羞怯。 LOL