【问题标题】:DataContractSerializer and Generic listsDataContractSerializer 和通用列表
【发布时间】:2014-07-09 11:46:09
【问题描述】:

我在从我的 xml 文件中反序列化列表时遇到问题。我的属性是内部的,所以我使用的是 datacontractserializer 而不是 xmlserializer。

我的xml如下

<?xml version="1.0" encoding="utf-8" ?>
<Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Root">
    <BackgroundColor>
        0,0,255
    </BackgroundColor>
    <RowGap>1</RowGap>
    <Table>
        <TableHeading>"H1"</TableHeading>
        <StartingColumn>A</StartingColumn>
    </Table>
    <Table>
        <TableHeading>"H2"</TableHeading>
        <StartingColumn>B</StartingColumn>
    </Table>    
</Root>

根有表列表。 ListOfTables 没有被反序列化。 类是

[DataContract()]
public class Root
{
    [OnDeserialized]
    internal void OnSerializingMethod(StreamingContext context)
    {
        if (Table == null)
        {
            Table = new List<TableStructure>();
        }
     }

     [DataMember(Name = "RowGap")]
     internal int RowGap { get; set; }

     [DataMember(Name = "TableHeaderBackgroundColor")]
     internal string HdrBackColor  { get; set; }

     [DataMember()]
     internal List<TableStructure> Table { get; set; }
}

[DataContract(Name = "Table", Namespace = "")]
public sealed class TableStructure 
{
    [DataMember]
    public string TableHeading { get; set; }

    [DataMember]
    public string StartingColumn { get; set; }
}

反序列化方法

internal static Root GetSettings()
{
     Root settings;
     using (FileStream fs = new FileStream("Root.xml", FileMode.Open, FileAccess.Read))
     {
          using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
          {
              var x = new DataContractSerializer(typeof(Root));
              settings = (Root)x.ReadObject(reader);
              reader.Close();
              fs.Close();
          }
     }
     return settings;
}

这执行没有任何错误,但不加载任何表信息。正在加载 RowGap 和颜色

【问题讨论】:

    标签: c# xml xml-serialization datacontractserializer xml-deserialization


    【解决方案1】:

    我修改了您的解决方案以使其正常工作(也添加了 XML 命名空间):

    [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Root")]
    public class Root
    {
        [OnDeserialized]
        internal void OnSerializingMethod(StreamingContext context)
        {
            if (Table == null)
            {
                Table = new List<TableStructure>();
            }
        }
    
        [DataMember(Name = "RowGap")]
        internal int RowGap { get; set; }
    
        [DataMember(Name = "TableHeaderBackgroundColor")]
        internal string HdrBackColor { get; set; }
    
        [DataMember(Name = "Tables")]
        internal List<TableStructure> Table { get; set; }
    }
    
    [DataContract(Name = "Table", Namespace = "http://schemas.datacontract.org/2004/07/Root")]
    public sealed class TableStructure
    {
        [DataMember(Name = "StartingColumn")]
        public string TableHeading { get; set; }
    
        [DataMember(Name = "TableHeading")]
        public string StartingColumn { get; set; }
    }
    

    XML 文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <Root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Root">
      <BackgroundColor>
        0,0,255
      </BackgroundColor>
      <RowGap>1</RowGap>
      <!-- Used as container element for list -->
      <Tables>
        <Table>
          <!-- Sorted elements alphabetically -->
          <StartingColumn>A</StartingColumn>
          <TableHeading>"H1"</TableHeading>
        </Table>
        <Table>
          <!-- Sorted elements alphabetically -->
          <StartingColumn>B</StartingColumn>
          <TableHeading>"H2"</TableHeading>
        </Table>
      </Tables>
    </Root>
    

    注意:DataContractSerializer 考虑了 XML 元素的顺序,如下所述:http://social.msdn.microsoft.com/Forums/vstudio/en-US/a891928b-d27a-4ef2-83b3-ee407c6b9187/order-of-data-members-in-the-xml-string-influences-deserialization-datacontractserializer?forum=wcf。由于您没有按字母顺序对元素进行排序,因此我修改了 XML 文件以满足DataContractSerializer 的行为。

    您可以使用DataMember 属性及其DataMember.Order 属性指定XML 元素的顺序。

    【讨论】:

      【解决方案2】:

      您是如何创建 xml 的?手动还是通过序列化程序? 应该有一个额外的&lt;Table&gt; 元素(代表Root.Table 属性)围绕现有的&lt;Table&gt; 元素(代表每个TableStructure 实例)。

      这个 xml(由 DataContractSerializer 创建)在我的机器上按预期反序列化:

      <Root xmlns="http://schemas.datacontract.org/2004/07/TestDataGrid" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <RowGap>101</RowGap>
          <Table>
              <Table xmlns="">
                  <StartingColumn>1</StartingColumn>
                  <TableHeading>First</TableHeading>
              </Table>
              <Table xmlns="">
                  <StartingColumn>2</StartingColumn>
                  <TableHeading>Second</TableHeading>
              </Table>
          </Table>
          <TableHeaderBackgroundColor>c0ffee</TableHeaderBackgroundColor>
      </Root>
      

      【讨论】:

      • 原来的Table元素没有xmlns属性,去掉属性反序列化会怎样?
      • 如果您从我发布的 xml 中删除空的 xmlns 属性,Tables 将不会反序列化。他们需要以某种方式告诉反序列化器该类驻留在与Root 不同的命名空间中。但是,如果您使用 same 命名空间 ([DataContract(Namespace = "")]) 标记 Root 类,则不会再在 xml 中获得这些 xmlns 属性。
      • 那么您应该在答案中提及您的更改
      • 嗯,这就是为什么我问原始 xml 来自哪里。它看起来不像是通过DataContractSerializer 制作的。
      • 是的,它是手工制作的。但是我之前尝试了一个额外的标签,它不起作用。我现在通过更正命名空间来修复它。谢谢
      猜你喜欢
      • 2011-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多