如何序列化List <list <object>&gt;?

时间:2017-02-27 15:56:58

标签: c# .net xml serialization .net-4.6

框架是c#.net 4.6.2

我正在从XML代码生成自动XML类

当我自动生成时,它会自动转换为Array[][]

但我想将其用作List<List<>>

我确信从Array到List的对话会导致一些序列化错误。我认为这是关于获取和设置功能。所以我需要你的帮助来解决这个问题

这是我编辑&gt;时自动生成的代码段粘贴特殊&gt;将XML粘贴为类

    /// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class OxFordDefinition_perGroup
{

    private string _GroupDescField;

    private string _GroupSenseField;

    private string _GroupGrammerField;

    private OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExampleField;

    /// <remarks/>
    public string _GroupDesc
    {
        get
        {
            return this._GroupDescField;
        }
        set
        {
            this._GroupDescField = value;
        }
    }

    /// <remarks/>
    public string _GroupSense
    {
        get
        {
            return this._GroupSenseField;
        }
        set
        {
            this._GroupSenseField = value;
        }
    }

    /// <remarks/>
    public string _GroupGrammer
    {
        get
        {
            return this._GroupGrammerField;
        }
        set
        {
            this._GroupGrammerField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
    public OxFordDefinition_perGroup_perMainExample_perSubExample[][] _perMainExample
    {
        get
        {
            return this._perMainExampleField;
        }
        set
        {
            this._perMainExampleField = value;
        }
    }
}

但是我想使用List<List<>>

而不是数组

所以我就像下面那样

        /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    public partial class OxFordDefinition_perGroup
    {

        private string _GroupDescField;

        private string _GroupSenseField;

        private string _GroupGrammerField;

        private  List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExampleField;

        /// <remarks/>
        public string _GroupDesc
        {
            get
            {
                return this._GroupDescField;
            }
            set
            {
                this._GroupDescField = value;
            }
        }

        /// <remarks/>
        public string _GroupSense
        {
            get
            {
                return this._GroupSenseField;
            }
            set
            {
                this._GroupSenseField = value;
            }
        }

        /// <remarks/>
        public string _GroupGrammer
        {
            get
            {
                return this._GroupGrammerField;
            }
            set
            {
                this._GroupGrammerField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
        public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
        {
            get
            {
                return this._perMainExampleField;
            }
            set
            {
                this._perMainExampleField = value;
            }
        }
    }

但是这次当我尝试序列化时会出现序列化错误

       public static string SerializeXML<T>(this T toSerialize)
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
        StringWriter textWriter = new StringWriter();
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }

这里是XML类的完整代码

http://pastebin.com/y5B8ENM3

这里给出的错误

enter image description here

1 个答案:

答案 0 :(得分:2)

实际上,您的原始版本和修改后的OxFordDefinition_perGroup都无法成功序列化。问题是XmlArrayItem.Type的值,这是constructor的第二个参数:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", typeof(OxFordDefinition_perGroup_perMainExample_perSubExample), IsNullable = false)]
public OxFordDefinition_perGroup_perMainExample_perSubExample[][] { get; set; }

根据docs

  

使用Type属性为公共字段或公共读/写属性值指定重写类型。

     

如果字段或属性返回Object类型的数组,则将XmlArrayItemAttribute的多个实例应用于字段或属性。对于每个实例,将Type属性设置为可以插入到数组中的对象类型。

typeof(OxFordDefinition_perGroup_perMainExample_perSubExample)表示最外层集合中的项目类型为typeof(OxFordDefinition_perGroup_perMainExample_perSubExample)。但是,实际上数组或列表中的项目分别是OxFordDefinition_perGroup_perMainExample_perSubExample[]List<OxFordDefinition_perGroup_perMainExample_perSubExample>类型,当然不能将其分配给此类型。此XmlSerializer代码生成失败。

如果您完全从[XmlArrayItem]属性中删除了类型设置,那么您的类型的两个版本都可以序列化为XML:

[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<List<OxFordDefinition_perGroup_perMainExample_perSubExample>> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

示例fiddle

<强>更新

你问,它增加了不应该存在的额外层。任何想法?

这是因为您使用的是嵌套列表或锯齿状数组。将其更改为简单列表或一维数组:

private List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExampleField;

/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("_perSubExample", IsNullable = false)]
public List<OxFordDefinition_perGroup_perMainExample_perSubExample> _perMainExample
{
    get
    {
        return this._perMainExampleField;
    }
    set
    {
        this._perMainExampleField = value;
    }
}

示例fiddle #2

然后我从http://pastebin.com/raw/BJhRfFNf下载了整个XML并运行xsd.exe以生成模式,然后从XML中生成类,并且我能够重现您的问题 - 生成了错误的类。然后我手动将锯齿状数组更改为平面数组(List<T>也能正常工作)并能够序列化和反序列化XML,而不会抛出异常:

示例fiddle #3

不幸的是,似乎只有第一个 </_perMainExample>节点使用这些调整的类成功反序列化,所以此时这个自动生成的代码似乎不可行。

我不确定为什么xsd.exe会在此处生成错误的代码,您可能想要提出另一个问题或者向Microsoft提出问题。

最终更新

看起来好像xsd.exe(因此将XML粘贴为类)在包含嵌套重复元素的重复元素时出现问题:

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

<_perMainExample>
  <_perSubExample>
  </_perSubExample>

  <_perSubExample>
  </_perSubExample>
</_perMainExample>

我不确定问题是什么,但此时我建议切换到不同的代码生成工具,例如https://xmltocsharp.azurewebsites.net/,它会生成以下类:

[XmlRoot(ElementName="_Example")]
public class _Example {
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
}

[XmlRoot(ElementName="_perSubExample")]
public class _perSubExample {
    [XmlElement(ElementName="_UpperTitle")]
    public string _UpperTitle { get; set; }
    [XmlElement(ElementName="_FormGroup")]
    public string _FormGroup { get; set; }
    [XmlElement(ElementName="_SenseNot")]
    public string _SenseNot { get; set; }
    [XmlElement(ElementName="_GrammaticNot")]
    public string _GrammaticNot { get; set; }
    [XmlElement(ElementName="_Desc")]
    public string _Desc { get; set; }
    [XmlElement(ElementName="_Example")]
    public List<_Example> _Example { get; set; }
    [XmlElement(ElementName="_Synonyms")]
    public string _Synonyms { get; set; }
}

[XmlRoot(ElementName="_perMainExample")]
public class _perMainExample {
    [XmlElement(ElementName="_perSubExample")]
    public List<_perSubExample> _perSubExample { get; set; }
}

[XmlRoot(ElementName="_perGroup")]
public class _perGroup {
    [XmlElement(ElementName="_GroupDesc")]
    public string _GroupDesc { get; set; }
    [XmlElement(ElementName="_GroupSense")]
    public string _GroupSense { get; set; }
    [XmlElement(ElementName="_GroupGrammer")]
    public string _GroupGrammer { get; set; }
    [XmlElement(ElementName="_perMainExample")]
    public List<_perMainExample> _perMainExample { get; set; }
}

[XmlRoot(ElementName="OxFordDefinition")]
public class OxFordDefinition {
    [XmlElement(ElementName="sourceURL")]
    public string SourceURL { get; set; }
    [XmlElement(ElementName="originDesc")]
    public string OriginDesc { get; set; }
    [XmlElement(ElementName="_perGroup")]
    public List<_perGroup> _perGroup { get; set; }
}

请注意:

  1. 生成的代码更清晰。

  2. 添加了额外级别的类_perMainExample以封装内部_perSubExample列表。

  3. 示例fiddle #4,通过调用XNode.DeepEquals()来显示原始和重新序列化的XML是相同的。