XML C# 中的反序列化 returns 空对象

XML deserialization in C# returns an empty object

我有一个关于反序列化的问题。我有一个 XML 文件,我需要将其反序列化为从服务引用中获取的 class。我知道如何反序列化一个 XML 文件,但是当我尝试反序列化这个文件时,我得到一个空的 class 对象。我不明白为什么要这样做。

XML 文件内容如下所示:

<?xml version="1.0" encoding="UTF-8" ?><iVAZFile xmlns="http://www.v.lt/c/i/iv">
<FileDescription>
<FileVersion>i1.3.3</FileVersion>
<FileDateCreated>2016-11-07T12:28:32</FileDateCreated>
<SoftwareCompanyName>otechnika&quot;</SoftwareCompanyName>
<SoftwareName>Eita</SoftwareName>
<SoftwareVersion>2016.9</SoftwareVersion>
<CreatorRegistrationNumber>123060356</CreatorRegistrationNumber>
</FileDescription>
</iVAZFile>

class 看起来像这样:

 [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.6.1590.0")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.v.lt/c/i/iv")]
    public partial class FileDescription : object, System.ComponentModel.INotifyPropertyChanged {

        private string fileVersionField;

        private System.DateTime fileDateCreatedField;

        private string softwareCompanyNameField;

        private string softwareNameField;

        private string softwareVersionField;

        private ulong creatorRegistrationNumberField;

        public FileDescription() {
            this.fileVersionField = "iVAZ1.3.3";
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=0)]
        public string FileVersion {
            get {
                return this.fileVersionField;
            }
            set {
                this.fileVersionField = value;
                this.RaisePropertyChanged("FileVersion");
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=1)]
        public System.DateTime FileDateCreated {
            get {
                return this.fileDateCreatedField;
            }
            set {
                this.fileDateCreatedField = value;
                this.RaisePropertyChanged("FileDateCreated");
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=2)]
        public string SoftwareCompanyName {
            get {
                return this.softwareCompanyNameField;
            }
            set {
                this.softwareCompanyNameField = value;
                this.RaisePropertyChanged("SoftwareCompanyName");
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=3)]
        public string SoftwareName {
            get {
                return this.softwareNameField;
            }
            set {
                this.softwareNameField = value;
                this.RaisePropertyChanged("SoftwareName");
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=4)]
        public string SoftwareVersion {
            get {
                return this.softwareVersionField;
            }
            set {
                this.softwareVersionField = value;
                this.RaisePropertyChanged("SoftwareVersion");
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Order=5)]
        public ulong CreatorRegistrationNumber {
            get {
                return this.creatorRegistrationNumberField;
            }
            set {
                this.creatorRegistrationNumberField = value;
                this.RaisePropertyChanged("CreatorRegistrationNumber");
            }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName) {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null)) {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }

以及我用来填充 class 的方法:

using (MemoryStream memoryStream = new MemoryStream())
            {
                using (BinaryWriter binWriter = new BinaryWriter(memoryStream, Encoding.UTF8))
                {
                    string filep = File.ReadAllText("test.xml");
                    binWriter.Write(filep);
                    memoryStream.Seek(2, SeekOrigin.Begin);
                    using (StreamReader streamReader = new StreamReader(memoryStream))
                    {
                        using (XmlReader reader = XmlReader.Create(streamReader))
                        {
                            XmlRootAttribute xRoot = new XmlRootAttribute();
                            xRoot.ElementName = "FileDescription";
                            xRoot.IsNullable = false;
                            XmlSerializer serializer = new XmlSerializer(typeof(FileDescription),xRoot);
                            FileDescription dsc = new FileDescription();
                            dsc=(FileDescription)serializer.Deserialize(reader);
                        }
                     }
                 }
               }

一些额外的评论来说明我也试过了:

  1. 我制作了自己的 class,看起来与服务参考中的相同,并添加了一个新参数 [XmlRoot(ElementName="FileDescription"),XmlType("FileDescription")] 然后反序列化对我的 class.
  2. 起作用
  3. 尝试在没有反序列化的情况下手动添加值,效果也很好,因此服务代码没有问题。
  4. 此外,当我反序列化 xml 时,我删除了 <iVAZFile xmlns="http://www.v.lt/c/i/iv"></iVAZFIle>,因为反序列化时它会抛出异常,而 .

最后说几句,我无法更改服务参考 class,我以后需要使用那个 class,所以我不能自己制作。

不同之处在于命名空间 - 根据 FileDescription class 上的 XmlType 属性,命名空间是 http://www.v.lt/c/i/iv。这适用于 FileDescription 的所有子元素。根命名空间是您通过 XmlRootAttribute 或采用默认命名空间的构造函数配置的任​​何内容。

正如我所建议的,调试此类问题的最简单方法是执行相反的操作 - 序列化 一个对象并查看它的外观。正如您在 this fiddle 中所见,目前的输出看起来像这样。这就是为什么你没有收到任何错误(因为根 class 匹配),但是你正在反序列化的 XML 中的所有子元素都在错误的命名空间中。

<FileDescription>
  <FileVersion xmlns="http://www.v.lt/c/i/iv">iVAZ1.3.3</FileVersion>
  <FileDateCreated xmlns="http://www.v.lt/c/i/iv">0001-01-01T00:00:00</FileDateCreated>
  <CreatorRegistrationNumber xmlns="http://www.v.lt/c/i/iv">0</CreatorRegistrationNumber>
</FileDescription>

如果您为根目录指定与 this fiddle 中相同的命名空间,则输出如下所示:

<FileDescription xmlns="http://www.v.lt/c/i/iv">
  <FileVersion>iVAZ1.3.3</FileVersion>
  <FileDateCreated>0001-01-01T00:00:00</FileDateCreated>
  <CreatorRegistrationNumber>0</CreatorRegistrationNumber>
</FileDescription>

您需要在修改后的文档中保留命名空间。你可以在 this fiddle.

中看到这个作品

(代表OP发表).

感谢 Charles Mager,问题已解决。问题是我必须将命名空间添加到 XML 中的每个值,因此它必须看起来像这样:

<FileDescription>
<FileVersion xmlns="http://www.v.lt/c/i/iv">i1.3.3</FileVersion>
<FileDateCreated xmlns="http://www.v.lt/c/i/iv">2016-11-07T12:28:32</FileDateCreated>
<SoftwareCompanyName xmlns="http://www.v.lt/c/i/iv">otechnika&quot;</SoftwareCompanyName>
<SoftwareName xmlns="http://www.v.lt/c/i/iv">Eita</SoftwareName>
<SoftwareVersion xmlns="http://www.v.lt/c/i/iv">2016.9</SoftwareVersion>
<CreatorRegistrationNumber xmlns="http://www.v.lt/c/i/iv">123060356</CreatorRegistrationNumber>
</FileDescription>

现在可以正常使用了,感谢帮助。