开发者

Deserialize List<ArrayList> object

I am trying to de-serialize a XML to object but I am getting stuck at one situation. Can anyone please help me out here.

XML:

<?xml version="1.0" ?>
<Level>
  <Warp_Blocks>
        <Warp_Block>
            <Block row="7" col="7" />
            <Block row="2" col="7" />
        </Warp_Block>
        <Warp_Block>
开发者_如何学Go            <Block row="4" col="4" />
            <Block row="3" col="7" />
        </Warp_Block>
  </Warp_Blocks>
</Level>

Code:

  [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>();
      }
   }

I am able to de-serialize to one level i.e. I get a List of Item objects but the individual Item objects don't contain the List of Block objects. What am I doing wrong here?


Change your LData class to this:

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

EDIT:
I don't know why it is not reading your second Warp_Block. The only possible reason I think can be that you are doing something else than what you have posted in the question. Here is the full example:

[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();
    }
}

It correctly outputs this:

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


I don't know exactly what you are doing here, but there is a gotcha with deserialization (at least binary deserialization. I don't know, but I suspect that it is the same for XML serialization). On deserializing a List<T> or a Dictionary<S,T>, the list is filled with null values (or default value if it is a value type) until the deserialization constructor has been exited. Only after exiting the constructor is the list filled with the actual, deserialized Ts.

This means that if you want to do something with the list, it cannot be done in the constructor. You can instead make a method which contains any work which needs to be done with the list, and as long as it is annotated with the [OnDeserializedAttribute] attribute, it will be called after the list has been filled but before the deserialization returns. The method can have any name.

See MSDN for details.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜