Robert Joseph Dacunto
Robert Joseph Dacunto

Reputation: 523

XML serialization of derived class in a list, need to set member on parent class

As a hobby, I'm making a 2D RPG in XNA and C#. I have a class called ObjectiveData. Its only member is a string called objectiveID. Derived from this are various other classes (GatherItemsObjectiveData, SpeakToNPCObjectiveData, etc) - all of them are suppose to store their own objective data related to that particular objective (gatherItemsObjectiveData would hold details on which item to collect and how many, etc). The only commonality between them is objectiveID, hence why it's in the parent class.

I had XML serialization of this working when each of the derived classes had their own objectiveID variable, but I want it to be in the parent class so that I can get the objectiveID without knowing what derived class it is, etc. When I made the switch to putting objectiveID in the parent, it no longer works (says XMl element "objective" not found). So now I'm trying to figure out how to get it to pass the objectiveID to its parent in the XML file.

C# Code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Serialization;

    namespace RpgLibrary.QuestClasses
    {
        public class ObjectivesData
        {
            [XmlArray("ObjectivesList")]
            [XmlArrayItem("KillXObjectiveData", typeof(KillXObjectiveData))]
            [XmlArrayItem("GatherXItemsObjectiveData", typeof(GatherXItemsObjectiveData))]
            [XmlArrayItem("SpeakToNPCObjectiveData", typeof(SpeakToNPCObjectiveData))]
            [XmlArrayItem("VisitAreaObjectiveData", typeof(VisitAreaObjectiveData))]
            public List<ObjectiveData> ObjectivesList;

            public ObjectivesData()
            {
                ObjectivesList = new List<ObjectiveData>();
            }
        }

        [XmlInclude(typeof(KillXObjectiveData))]
        [XmlInclude(typeof(GatherXItemsObjectiveData))]
        [XmlInclude(typeof(SpeakToNPCObjectiveData))]
        [XmlInclude(typeof(VisitAreaObjectiveData))]
        public class ObjectiveData
        {
            public string objectiveID;

            public ObjectiveData()
            {

            }

            public ObjectiveData(string objectiveID)
            {
                this.objectiveID = objectiveID;
            }
        } 

        [XmlType(TypeName = "KillXObjectiveData")]
        public class KillXObjectiveData : ObjectiveData
        {
            public string killTotal;
            public string npcID;

            public KillXObjectiveData()
            {

            }

            public KillXObjectiveData(string killTotal, string npcID, string objectiveID)
                : base(objectiveID)
            {
                this.killTotal = killTotal;
                this.npcID = npcID;
            }
        }

        [XmlType(TypeName = "GatherXItemsObjectiveData")]
        public class GatherXItemsObjectiveData : ObjectiveData
        {
            public string gatherTotal;
            public string itemID;

            public GatherXItemsObjectiveData()
            {

            }

            public GatherXItemsObjectiveData(string gatherTotal, string itemID, string objectiveID)
                : base(objectiveID)
            {
                this.gatherTotal = gatherTotal;
                this.itemID = itemID;
            }
        }

        [XmlType(TypeName = "SpeakToNPCObjectiveData")]
        public class SpeakToNPCObjectiveData : ObjectiveData
        {
            public string npcID;

            public SpeakToNPCObjectiveData()
            {

            }

            public SpeakToNPCObjectiveData(string npcID, string objectiveID)
                : base(objectiveID)
            {
                this.npcID = npcID;
            }
        }

        [XmlType(TypeName = "VisitAreaObjectiveData")]
        public class VisitAreaObjectiveData : ObjectiveData
        {
            public string areaID;

            public VisitAreaObjectiveData()
            {

            }

            public VisitAreaObjectiveData(string areaID, string objectiveID)
                : base(objectiveID)
            {
                this.areaID = areaID;
            }
        }
    }

XML file:

  <?xml version="1.0" encoding="utf-8"?>
  <XnaContent xmlns:QuestClasses="RpgLibrary.QuestClasses">
    <Asset Type="QuestClasses:ObjectivesData">
        <ObjectivesList>
          <Item Type="QuestClasses:GatherXItemsObjectiveData">
            <gatherTotal>5</gatherTotal>
            <itemID>1</itemID>
            <objectiveID>1</objectiveID>
          </Item>
          <Item Type="QuestClasses:KillXObjectiveData">
            <killTotal>5</killTotal>
            <npcID>900</npcID>
            <objectiveID>2</objectiveID>
          </Item>
        </ObjectivesList>
    </Asset>
  </XnaContent>

The end result should be that I get a list of ObjectiveData with all the derived class objects stored in it, and I just need the objectiveID to be properly set in the parent class.

Upvotes: 2

Views: 161

Answers (1)

dbc
dbc

Reputation: 116615

According to Everything you ever wanted to know about IntermediateSerializer:

Base class members are serialized before data from the derived type

Thus you need to move the <objectiveID> element to the beginning of its containing element in pre-existing XML files.

Upvotes: 1

Related Questions