【问题标题】:Deserialize List<ArrayList> object反序列化 List<ArrayList> 对象
【发布时间】:2011-02-16 12:43:22
【问题描述】:

我正在尝试将 XML 反序列化为对象,但我遇到了一种情况。任何人都可以在这里帮助我。

XML:

<?xml version="1.0" ?>
<Level>
  <Warp_Blocks>
        <Warp_Block>
            <Block row="7" col="7" />
            <Block row="2" col="7" />
        </Warp_Block>
        <Warp_Block>
            <Block row="4" col="4" />
            <Block row="3" col="7" />
        </Warp_Block>
  </Warp_Blocks>
</Level>

代码:

  [XmlRoot("Level")]
   public class LData
    {
        [XmlArray("Warp_Blocks")]
        [XmlArrayItem("Warp_Block",typeof(WarpBlock),IsNullable = false)]
        public List<WarpBlock> WarpBlocks;
    }
   public class LBlock
   {
      [XmlAttribute("row")]
      public int row;
      [XmlAttribute("col")]
      public int col;
   }
   public class WarpBlock
   {
      [XmlArray("Warp_Block")]
      [XmlArrayItem("Block",typeof(LBlock),IsNullable= false)]
      public List<LBlock> WarpBlocks;

      public WarpBlock()
      {
            WarpBlocks = new List<LBlock>();
      }
   }

我能够反序列化到一个级别,即我得到一个 Item 对象列表,但各个 Item 对象不包含 Block 对象列表。我在这里做错了什么?

【问题讨论】:

  • class Items - 这是您的问题,或者我们没有查看真实代码。
  • 你如何反序列化?如果您使用的是XmlSerializer,您可能需要公开您的课程。
  • @Henk - 无法在这里发布原始代码..所以不得不做这个例子..但我希望你能得到我想要做的事情。
  • @Nekresh - 是的。所有课程都是公开的。
  • @Sharath:我更喜欢原件的复制粘贴,也许有一些删除。这很有可能让我们追查您的拼写错误而不是问题。

标签: c# xml deserialization


【解决方案1】:

将您的 LData 类更改为:

[XmlRoot("Level")]
public class LData
{
    [XmlElement("Warp_Blocks")]
    public List<WarpBlock> WarpBlocks;
}

编辑:
我不知道为什么它没有读取您的第二个 Warp_Block。我认为唯一可能的原因可能是您正在做的事情与您在问题中发布的内容不同。这是完整的示例:

[XmlRoot("Level")]
public class LData
{
    [XmlElement("Warp_Blocks")]
    public List<WarpBlock> WarpBlocks;
}
public class LBlock
{
    [XmlAttribute("row")]
    public int row;
    [XmlAttribute("col")]
    public int col;
}
public class WarpBlock
{
    [XmlArray("Warp_Block")]
    [XmlArrayItem("Block", typeof(LBlock), IsNullable = false)]
    public List<LBlock> WarpBlocks;

    public WarpBlock()
    {
        WarpBlocks = new List<LBlock>();
    }
}
public class Program
{
    public static void Main()
    {
        string test =
            "<?xml version=\"1.0\" ?>" +
            "<Level>" +
            "  <Warp_Blocks>" +
            "        <Warp_Block>" +
            "            <Block row=\"7\" col=\"7\" />" +
            "            <Block row=\"2\" col=\"7\" />" +
            "        </Warp_Block>" +
            "        <Warp_Block>" +
            "            <Block row=\"4\" col=\"4\" />" +
            "            <Block row=\"3\" col=\"7\" />" +
            "        </Warp_Block>" +
            "  </Warp_Blocks>" +
            "</Level>";

        byte[] byteArray = Encoding.ASCII.GetBytes(test);
        MemoryStream stream = new MemoryStream(byteArray);

        XmlSerializer s = new XmlSerializer(typeof (LData));
        LData data = (LData) s.Deserialize(stream);

        foreach (var a in data.WarpBlocks)
            foreach (var b in a.WarpBlocks)
                Console.WriteLine(b.row + ", " + b.col);

        Console.ReadKey();
    }
}

它正确地输出了这个:

7, 7
2, 7
4, 4
3, 7

【讨论】:

  • @Yogesh - 试过这个......所以我可以将第一个元素读入列表,但不能读入第二个......
  • 你说的第二个元素是什么?
  • 在上面的 XML 中,Warp_Blocks 包含了两个 Warp_Block 对象,但它目前只读取第一个..
  • @Yogesh - 我已经仔细检查了代码,它们很相似。唯一的区别是我使用 XmlTextReader 从文件中读取 XML,然后对其进行反序列化。
  • @Yogesh - 我很抱歉.. 这行得通,但不完全是我想要的方式。输出实际上是一个包含所有 4 个 Block 项的 WarpBlock 对象。但实际上我想要的是每 2 个 WarpBlock 对象,其中包含两个 Blocks。
【解决方案2】:

我不确切知道您在这里做什么,但是反序列化有一个问题(至少是二进制反序列化。我不知道,但我怀疑 XML 序列化也是如此)。在反序列化 List&lt;T&gt;Dictionary&lt;S,T&gt; 时,列表将填充 null 值(或默认值,如果它是值类型),直到退出反序列化构造函数。只有在退出构造函数后,列表才会填充实际的、反序列化的Ts。

这意味着如果你想对列表做一些事情,它不能在构造函数中完成。您可以改为创建一个方法,其中包含需要对列表完成的任何工作,并且只要使用[OnDeserializedAttribute] 属性对其进行注释,它就会在列表被填充后调用但是反序列化返回之前。该方法可以有任何名称。

详情请见MSDN

【讨论】:

  • 我试过这个.. 用于 WarpBlock 类,但输出没有变化
猜你喜欢
  • 2015-03-18
  • 2020-08-02
  • 2015-05-29
  • 2015-06-28
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 2014-05-07
  • 2014-02-08
相关资源
最近更新 更多