C# XmlSerializer.Deserialize子类(不是数组)

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> <

所以这让我难堪了好几个小时。。。我的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;
“我的办公室”对象定义如下:

    [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对象
自定义对象和办公对象都在住宅对象上实例化。我尝试将Office对象放在自定义对象上(以匹配xml结构),但这没有什么区别。自定义序列化正确,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