反序列化 List<ArrayList> 对象

4

我正在尝试将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 - 要么这是你的问题,要么我们没有看到真正的代码。 - H H
你如何进行反序列化?如果你正在使用 XmlSerializer,你可能需要将你的类设为公共类。 - Nekresh
@Henk - 无法在此处发布原始代码..所以不得不制作这个示例..但我希望你明白我想做什么。 - Sharath
@Nekresh - 是的,所有类都是公共的。 - Sharath
@Sharath:我更喜欢原文复制粘贴,可能删掉一些内容。这样有很大的风险,我们会追踪你的拼写错误而不是问题本身。 - H H
@Henk - 已经做出更改...这是我正在使用的类。 - Sharath
2个回答

4

将您的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 - 尝试过了,我能将第一个元素读入列表,但是第二个却读不进去。 - Sharath
你在谈论哪个第二元素? - Yogesh
在上面的 XML 中,Warp_Blocks 包含两个 Warp_Block 对象,但目前只读取第一个。 - Sharath
@Yogesh - 我已经仔细检查了代码,它们是相似的。唯一的区别是我正在使用XmlTextReader从文件中读取XML,然后进行反序列化。 - Sharath
@Yogesh - 对不起,这个代码确实可以运行,但并不完全符合我的要求。实际上输出的是一个 WarpBlock 对象,其中包含了所有 4 个 Block 项。但是事实上我想要的是每个 WarpBlock 对象中包含两个 Block 的两个 WarpBlock 对象。 - Sharath
请更新您的问题,提供准确的XML和您想要的准确输出。 - Yogesh

0

我不确定你在这里做什么,但是反序列化有一个陷阱(至少是二进制反序列化。我不知道,但我怀疑 XML 序列化也是一样的)。在反序列化 List<T>Dictionary<S,T> 时,列表将填充 null 值(或默认值,如果它是值类型),直到反序列化构造函数已退出。只有在退出构造函数后,列表才会填充实际的、反序列化的 T

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

详见 MSDN


我尝试了这个... 对于 WarpBlock 类,但输出没有变化。 - Sharath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接