我在联合中创建了一个基于瓷砖的游戏,并在地图和tile类型的架构中遇到了问题。当平铺类型改变时,平铺类包含类似事件的逻辑。当我试图将类型保存到磁盘时,这些事件也被序列化了,这是我不想要的(在联合中造成了几个问题)。我基本上是想确保我只保存像x,y位置和枚举类型这样的纯数据。以下是我的做法:
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编程中的数据传输对象。这样,我确信我的数据仍然是可串行化的,并且当我保存一个平铺地图并同时修改它时,我不会遇到问题。
然而,它也意味着重复的代码和更多的转换方法。你觉得我的方法怎么样?您会修改平铺类以使其正确序列化吗?我相信,我还需要包括复制方法,以确保保存到磁盘工作,同时修改映射状态等。
发布于 2016-05-22 17:27:52
我一直在试验,发现这个解决方案是最好的:
[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数组。当将数据写入磁盘时,我会在保存之前复制所有内容,以避免在用户更改当前映射实例时在另一个线程上保存时出现问题。
我仍然乐意阅读任何关于如何改进我的课堂设计的建议。
https://codereview.stackexchange.com/questions/128759
复制相似问题