带有派生对象的C#XML序列化

本文关键字:C#XML 序列化 对象 派生 | 更新日期: 2023-09-27 18:19:39

我一直在使用本系列教程在XNA中编程2D RPG:http://xnagpa.net/xna4rpg.php

作者从未完成,但我一直在继续,并取得了很大进展(碰撞检测、NPC路径、库存等)。现在我正在开发一个事件系统(转换到不同的级别,与NPC互动,任务等等)。它非常简单,但这是我的初始设置:

public abstract class GameEvent
{
    #region Field Region
    protected Point eventPosition;
    #endregion
    #region Property Region
    public Point EventPosition
    {
        get { return eventPosition; }
    }
    #endregion
    #region Constructor Region
    public GameEvent()
    {
    }
    public GameEvent(Point eventPosition)
    {
        this.eventPosition = eventPosition;
    }
    #endregion
}
public class LevelTransitionEvent : GameEvent
{
    #region Field Region
    public Point teleportPosition;
    public string mapName;
    #endregion
    #region Constructor Region
    public LevelTransitionEvent()
    {
    }
    public LevelTransitionEvent(Point eventPosition, Point teleportPosition, 
        string mapName)
        : base(eventPosition)
    {
        this.teleportPosition = teleportPosition;
        this.mapName = mapName;
    }
    #endregion
}

我使用教程中开始的关卡编辑器来制作地图,添加NPC,现在添加事件。它的工作方式是使用XML序列化/取消序列化。它适用于所有事情(添加瓦片、NPC、宝箱),但现在我正尝试添加这些事件,从级别转换事件开始。

这是处理序列化的教程中的代码:

static class XnaSerializer
{
    public static void Serialize<T>(string filename, T data)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        using (XmlWriter writer = XmlWriter.Create(filename, settings))
        {
            IntermediateSerializer.Serialize<T>(writer, data, null);                
        }
    }
    public static T Deserialize<T>(string filename)
    {
        T data;
        using (FileStream stream = new FileStream(filename, FileMode.Open))
        {
            using (XmlReader reader = XmlReader.Create(stream))
            {
                data = IntermediateSerializer.Deserialize<T>(reader, null);
            }
        }
        return data;
    }
}

序列化级别:

  XnaSerializer.Serialize<LevelData>(LevelPath + levelData.LevelName + ".xml", levelData);

现在我只是想让它发挥作用,所以我包含了一个简单的事件:

        levelData.GameEvents.Add(new LevelTransitionEvent(new Point(0,0), new Point(5,5), "temp"));

levelData.GameEvents是一个GameEvent类型列表。

这是XML输出:

 <?xml version="1.0" encoding="utf-8"?>
 <XnaContent xmlns:WorldClasses="RpgLibrary.WorldClasses"                                                                            xmlns:EventClasses="XRpgLibrary.EventClasses">
 <Asset Type="WorldClasses:LevelData">
 <LevelName>test 6</LevelName>
 <MapName>6</MapName>
 <MapWidth>100</MapWidth>
 <MapHeight>100</MapHeight>
 <Characters />
 <Chests />
 <GameEvents>
  <Item Type="EventClasses:LevelTransitionEvent">
    <teleportPosition>5 5</teleportPosition>
    <mapName>temp</mapName>
  </Item>
</GameEvents>
<TrapNames />
 </Asset>
 </XnaContent>

由于某种原因,基类变量eventPosition没有被包括在内。我是否需要添加一些额外的功能,以使基类成员数据也包含在xml序列化中?感谢

带有派生对象的C#XML序列化

使用标准.NET XmlSerializerIntermediateSerializer与之类似)时,所有要序列化/反序列化的属性都必须具有公共getter和setter。

请参阅此处了解详细信息:为什么';我的公共属性是否由XmlSerializer序列化?

MS文档中有一个关于使用XNA序列化游戏数据的简单教程:http://msdn.microsoft.com/en-us/library/bb203924.aspx(请注意,这直接使用XmlSerializer)。

通过将您的财产更改为:

   public Point EventPosition
    {
        get { return eventPosition; }
        set { eventPosition = value; }
    }

您现在应该在序列化的输出结果中看到它。

默认情况下,IntermediateSerializer仅使用公共get和set访问器序列化公共字段或属性。要使它序列化较少的公共字段,请使用[ContentSerializer]属性:
[ContentSerializer]
public Point EventPosition
{
    get { return eventPosition; }
}

有关更多信息,请参阅:您想了解的关于IntermediateSerializer 的一切