首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在序列化类型时将数据与逻辑分离-网格平铺映射示例

如何在序列化类型时将数据与逻辑分离-网格平铺映射示例
EN

Code Review用户
提问于 2016-05-19 12:59:41
回答 1查看 176关注 0票数 4

我在联合中创建了一个基于瓷砖的游戏,并在地图和tile类型的架构中遇到了问题。当平铺类型改变时,平铺类包含类似事件的逻辑。当我试图将类型保存到磁盘时,这些事件也被序列化了,这是我不想要的(在联合中造成了几个问题)。我基本上是想确保我只保存像x,y位置和枚举类型这样的纯数据。以下是我的做法:

代码语言:javascript
复制
public class Tile
{
    public event EventHandler<TileTypeChangedEventArgs> TileTypeChanged;

    public const TileType defaultType = TileType.Empty;

    public TileType type
    {
        get { return _type; }
        set
        {
            if (Enum.IsDefined(typeof(TileType), value) == false)
                throw new InvalidOperationException("Trying to set undefined tile type.");

            if (value != _type)
            {
                _type = value;
                var args = new TileTypeChangedEventArgs(_type);
                OnTileTypeChanged(args);
            }
        }
    }

    public int x { get { return _x; } }
    public int z { get { return _z; } }

    TileType _type;

    readonly int _x;
    readonly int _z;

    public Tile(int x, int z, TileType type = Tile.defaultType)
    {
        _x = x;
        _z = z;
        this.type = type;
    }

    protected virtual void OnTileTypeChanged(TileTypeChangedEventArgs e)
    {
        var handler = TileTypeChanged;
        if (handler != null)
            handler.Invoke(this, e);
    }
}

public class TileTypeChangedEventArgs : EventArgs
{
    public TileType type { get; private set; }

    public TileTypeChangedEventArgs(TileType type)
    {
        this.type = type;
    }
}

public enum TileType
{
    Empty,
    Grass,
    Water,
    Dirt
}

[Serializable]
public sealed class TileData
{
    public static readonly int version = 1;

    public TileType type
    {
        get { return _type; }
        set { _type = value; }
    }

    public int x
    {
        get { return _x; }
        set { _x = value; }
    }

    public int z
    {
        get { return _z; }
        set { _z = value; }
    }

    TileType _type;
    int _x;
    int _z;

    public static TileData Convert(Tile tile)
    {
        var data = new TileData();
        data.x = tile.x;
        data.z = tile.z;
        data.type = tile.type;
        return data;
    }

    public static Tile Convert(TileData data)
    {
        return new Tile(data.x, data.z, data.type);
    }
}

我创建TileData类是因为它的工作方式类似于web编程中的数据传输对象。这样,我确信我的数据仍然是可串行化的,并且当我保存一个平铺地图并同时修改它时,我不会遇到问题。

然而,它也意味着重复的代码和更多的转换方法。你觉得我的方法怎么样?您会修改平铺类以使其正确序列化吗?我相信,我还需要包括复制方法,以确保保存到磁盘工作,同时修改映射状态等。

EN

回答 1

Code Review用户

发布于 2016-05-22 17:27:52

我一直在试验,发现这个解决方案是最好的:

代码语言:javascript
复制
[Serializable]
public class Tile
{
    [field: NonSerialized]
    public event EventHandler<TileTypeChangedEventArgs> TileTypeChanged;

    [NonSerialized]
    public const TileType defaultType = TileType.Empty;

    public TileType type
    {
        get { return _type; }
        set
        {
            if (Enum.IsDefined(typeof(TileType), value) == false)
                throw new InvalidOperationException("Trying to set undefined tile type.");

            if (value != _type)
            {
                _type = value;
                var args = new TileTypeChangedEventArgs(_type);
                OnTileTypeChanged(args);
            }
        }
    }

    public int x { get; private set; }
    public int z { get; private set; }

    TileType _type;

    public Tile() { }

    public Tile(int x, int z, TileType type = Tile.defaultType)
    {
        this.x = x;
        this.z = z;
        this.type = type;
    }

    public Tile(Tile original)
    {
        this.x = original.x;
        this.z = original.z;
        this.type = original.type;
    }

    public override string ToString()
    {
        return string.Format("Tile: {0}|{1} = {2}", x, z, type);
    }

    protected virtual void OnTileTypeChanged(TileTypeChangedEventArgs e)
    {
        var handler = TileTypeChanged;
        if (handler != null)
            handler.Invoke(this, e);
    }
}

public class TileTypeChangedEventArgs : EventArgs
{
    public TileType type { get; private set; }

    public TileTypeChangedEventArgs(TileType type)
    {
        this.type = type;
    }
}

public enum TileType
{
    Empty,
    Grass,
    Water,
    Dirt
}

问题在于事件的偶然序列化。我不知道属性的NonSerialized :字段属性,但这对于BinaryFormatter、XmlSerializer和Json.Net非常有用。我还必须为后面添加一点ContractResolver逻辑,以反序列化私有属性,但我发现它比在数据类中提供更多属性要干净得多。

另一件需要注意的事情是在Tile类中以及在Map中使用一个复制构造函数,它包含一个tiles数组。当将数据写入磁盘时,我会在保存之前复制所有内容,以避免在用户更改当前映射实例时在另一个线程上保存时出现问题。

我仍然乐意阅读任何关于如何改进我的课堂设计的建议。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/128759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档