【问题标题】:How to serialize/deserialize an object matrix to/from xml in C#?如何在 C# 中序列化/反序列化对象矩阵到/从 xml?
【发布时间】:2020-03-10 11:53:48
【问题描述】:

我有一个任务是保存和加载扫雷板。我在保存电路板矩阵时遇到问题。这些是我的扫雷属性:

[XmlIgnore]
public Tile[,] Grid { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public int NumberOfMines { get; set; }

平铺属性:

public int X { get; set; }
public int Y { get; set; }
public int NeighbourMines { get; set; }
public bool IsMine { get; set; }
public bool IsRevealed { get; set; }
public bool IsFlagged { get; set; }

我尝试过这样的事情:

public List<Tile> ListFromMatrix
{
    get
    {
        List<Tile> temp = new List<Tile>(Height * Width);
        for (int i = 0; i < Height; i++)
            for (int j = 0; j < Width; j++)
                temp.Add(Grid[i, j]);
        return temp;
    }
    set
    {
        //Grid = new Tile[Height, Width];
        int it = 0;
        for (int i = 0; i < Height; i++)
            for (int j = 0; j < Width; j++)
                Grid[i, j] = value[it++];
    }
}

保存到文件中可以正常工作,但从中加载会导致异常。而且我真的不知道如何调试它,因为异常被抛出:

//this.Game is the Minesweeper reference in the main form
this.Game = (Game)xs.Deserialize(fileStream);

感谢任何帮助!

编辑:这是个例外

System.InvalidOperationException: 'XML 文档中存在错误 (7, 4)。 内部异常 1:NullReferenceException:对象引用未设置为对象的实例。

EDIT2:保存代码

SaveFileDialog sfd = new SaveFileDialog();
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(Game));
                    xs.Serialize(fs, this.Game);
                }
            }

EDIT3:这里是xml内容https://pastebin.com/0vkxQC5A

EDIT4:感谢您的尝试,但没有任何效果,所以我将重写代码以使用列表而不是矩阵。

【问题讨论】:

  • 抛出了什么异常?
  • 我已经编辑了帖子,但抛出了异常
  • 我自己不会在这里使用数组[,]。特别是在需要序列化的时候。我会选择一个简单的 List 然后计算所需的索引,例如 IndexOfTile = Game.Height * row + column。
  • 我正考虑重写所有内容,但我想要一个更优雅的解决方案。
  • 老手的小费,先搞定吧。

标签: c# xml matrix serialization deserialization


【解决方案1】:

您可以尝试像这样更改您的设置:

set
{
    var height = value.Max(t=>t.Y);
    var width = value.Max(t=>t.X);
    Grid = new Tile[height, width];
    foreach(var tile in value)
    {
      Grid[tile.Y,tile.X]=tile;
    }
}

您可能不想使用游戏对象的 height 和 width 属性,因为您需要假设这些属性在此属性之前设置。还不如自己计算。当你在做的时候,不妨也改变一下 get ,然后扔掉高度/宽度,或者改变它们以实际拉取网格的当前宽度/高度:

get
{
    var temp = new List<Tile>(Grid.Length);
    for (int i = 0; i < Grid.GetLength(0); i++)
        for (int j = 0; j < Grid.GetLength(1); j++)
            temp.Add(Grid[i, j]);
    return temp;
}

【讨论】:

  • 我试过这个解决方案,即使是硬编码值也会抛出同样的异常
【解决方案2】:

似乎错误在于反序列化您的属性 ListFromMatrix。

public List<Tile> ListFromMatrix {get; set;}


// when it comes time to serialize
ListFromMatrix = CreateList();
using (FileStream fs = new FileStream(sfd.FileName, FileMode.Create))
{
    XmlSerializer xs = new XmlSerializer(typeof(Game));
    xs.Serialize(fs, this.Game);
}

private List<Tile> CreateList()
{
    var temp = new List<Tile>(Height * Width);
    for (int i = 0; i < Height; i++)
        for (int j = 0; j < Width; j++)
            temp.Add(Grid[i, j]);
    return temp;
}

【讨论】:

    猜你喜欢
    • 2013-09-24
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多