简体   繁体   中英

C# XML serialization with derived objects

I've been programming a 2D RPG in XNA using this tutorial series: http://xnagpa.net/xna4rpg.php

The author never finished, but I've continued on and made a lot of progress (collision detection, NPC pathing, inventory, and more). Right now I'm working on an event system (transitioning to a different level, interacting with NPCs, quests and so on). It's very bare bones but this is my initial set up:

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
}

I use the level editor that was started in the tutorial to make the map, add NPCs and now to add events. The way it works is using XML serialization/deserialziation. It works fine for everything (adding tiles, NPCs, treasure chests) but now I'm trying to add these events, starting with level transition events.

This is the code from the tutorial dealing with serialization:

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;
    }
}

Serializing the level:

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

Right now I'm just trying to get it to work, so I included a simple event:

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

levelData.GameEvents is a List of GameEvent type.

This is the XML output:

 <?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>

For some reason, the base class variable, eventPosition, is not being included. Is there some additional feature I have to add to get the base class member data to also include in the xml serialization? Thanks

When using the standard .NET XmlSerializer (to which the IntermediateSerializer is similar), all properties that are to be serialized / deserialized must have a public getter and setter.

See here for details on this: Why isn't my public property serialized by the XmlSerializer?

The MS documentation has a simple tutorial also on serializing game data with XNA here: http://msdn.microsoft.com/en-us/library/bb203924.aspx (note that this uses the XmlSerializer directly).

By changing your property to:

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

you should now see it in the output result of the serialization.

The IntermediateSerializer, by default, only serializes public fields or properties with both public get and set accessors. To have it serialize less public fields, use the [ContentSerializer] attribute:

[ContentSerializer]
public Point EventPosition
{
    get { return eventPosition; }
}

For more information, see: Everything you ever wanted to know about IntermediateSerializer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM