C# XmlSerializer.Deserialize子类(不是数组)
所以这让我难堪了好几个小时。。。我的xml结构如下所示:C# XmlSerializer.Deserialize子类(不是数组),c#,xml,visual-studio-2010,debugging,serialization,C#,Xml,Visual Studio 2010,Debugging,Serialization,所以这让我难堪了好几个小时。。。我的xml结构如下所示: <custom> <priceLower>999999</priceLower> <priceUpper>1000001</priceUpper> <investment>true</investment> <offtheplan>false</offtheplan> <office> <
<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>
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;
“我的办公室”对象定义如下:
[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; }
[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 }
反序列化代码(由帮助器类调用,并接收包含自定义对象(其中包含Office对象)的属性对象)如下所示:
<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>
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;
所以。。。自定义对象完全反序列化。。没有问题。但是office one没有,它的所有属性都是空的
有没有办法精确地指定xml树中哪个元素包含Office对象的数据?我曾尝试将Office对象移动到与Custom(在Property对象上)相同的级别,这确实更有意义,但这也不起作用-我将其移动到Custom下,以匹配xml结构,因为我无法更改它,而且我找不到方法指定从何处获取数据
我在这里又经历了一点奇怪。。。我添加了一个序列化程序函数,它基本上从反序列化对象创建一个新的XML文件。我可以一直调试到调用Serialize函数的地方——如果我在对象序列化之前查看对象内部,我可以看到Office对象只包含空值。但是序列化程序实际上将数据序列化到我的新XML文件中
这就是它变得更奇怪的地方。如果在调用Serialize()之前查看对象,那么它将始终序列化空元素。但是,如果我在序列化发生之前不查看该对象的内部,它会将数据序列化到其中。我已经多次证实了这一点——毫无疑问,这就是行为。有人见过这样的事吗?框架是否在捉弄我,如果是,为什么
更新:
为了澄清,我的XML看起来是这样的(我只展示了上面的一个例子):
这里的办公室名称
所以这里有几个层次的嵌套,这可能是我的问题,尽管我认为这更像是一个VS问题
反序列化程序正在处理完整的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>
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;
住宅:属性:基本属性类型
- 包含自定义对象
- 包含Office对象
visualstudio调试器是否有可能成为这里的“红鲱鱼”。正如我前面提到的,如果我调试并查看反序列化对象,它会显示为空,然后当我将其序列化回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);
}
}
}
[可序列化]
[XmlRoot(“自定义”)]
公共阶级习俗
{
[XmlElement(“投资”)]
公共字符串投资{get;set;}
[XmlElement(“计划外”)]
计划的公共字符串{get;set;}
[XmlElement(“价格更低”)]
公共十进制?价格下限{get;set;}
[XmlElement(“价格上限”)]
公共十进制?价格上限{get;set;}
[XmlElement(“办公室”)]
公共办公室{get;set;}
}
[可序列化]
公课办公室
{
//用于调试目的的临时文件:
私有字符串_officeName;
[XmlElement(“名称”)]
公共字符串名称{get;set;}
[XmlElement(“officeName”)]
公共字符串OfficeName{get;set;}
[XmlElement(“addressL1”)]
公共字符串地址1{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
字符串xml=@“
999999
1000001
真的
假的
墨尔本办公室
总公司
";
XmlSerializer s=新的XmlSerializer(typeof(Custom));
//没有这个很好
//XmlAttributeOverrides attrOverrides=新的XmlAttributeOverrides();
//var attrs=新的XmlAttributes();
//var attr=new XmlElementAttribute();
//attr.ElementName=“办公室”;
//属性类型=类型(办公室);
//attrs.xmlements.Add(attr);
//添加(办公室类型),“办公室”,属性;
//s=新的XmlSerializer(typeof(Custom),attrOverrides);
使用(StringReader=new StringReader(xml))
{
自定义c=(自定义)s.反序列化(读取器);
}
}
}
哈哈哈。。。我真是个傻瓜!让一个同事和我一起经历了这件事,我们发现我做了一件非常愚蠢的事,那就是:
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()覆盖,然后它会对所有值进行加核
我不觉得害羞吗。哈哈好吧。。。当你说它可以处理“简单的层次结构”。。。这是否意味着它无法处理我试图序列化的结构(即3层深度)?我在任何地方都找不到关于这种类型结构的任何文档,除了集合(我的不是)。不,我不认为深度是个问题(例如,我发布的代码有3层深度,可以很好地工作)。这是另外一回事——也许是你的基础课?Office类中是否缺少无参数构造函数?你可以编辑你的帖子来包含SSCCE(或者发布在GitHub上)吗?这里肯定有一个无参数的cont