Sign in to follow this  
Crehl

C# - XML Serialization - Serializing a class as an attribute?

Recommended Posts

Crehl    134
With the game I'm currently working, I planned to store levels in XML format (With the default levels stored as resources, but with user-creatable levels in XML files). I've decided to use .NET's own XmlSerializer class, however I've run across a problem. I have a class, Vector, that I want to serialize into the form "X,Y". This works fine if it's stored as an element, but I'd rather have it as an attribute, as
<Cannon LaunchVector="14,8" />
is more compact and looks nicer (Not to mention, makes more sense) than:
<Cannon><LaunchVector>14,8</LaunchVector></Cannon>
When I try to compile with this code:
		private Vector launchVector;
		/// <summary>
		/// Gets and sets the vector that the ball is automatically
		/// launched along. Only used in the 'menu' level.
		/// </summary>
		[XmlElement(ElementName = "LaunchVector")]
		public Vector LaunchVector
		{
			get { return launchVector; }
			set { launchVector = value; }
		}


it all compiles, and runs, fine. However, if I try to use an attribute:
		[XmlAttribute(AttributeName = "LaunchVector")]


it throws an exception at runtime: "There was an error reflecting Cannons.LevelData" at this line:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(LevelData));


I don't want to over-paste code, so I chopped it down a lot, but hopefully I haven't missed anything important. Hope some can help, Thanks - Crehl.

Share this post


Link to post
Share on other sites
theOcelot    498
First solution off the top of my head is to get the vector as a string and parse it yourself. String constructor for vector class? It wouldn't be bad if you used a std::istringstream (or strstream, I always forget).

Share this post


Link to post
Share on other sites
VizOne    598
XmlAttribute does not support complex types.

I see two possible solutions:

a) Make the Canon class implement IXmlSerializer, which means that you can control serialization for this class:


class Canon : ISerializable{
public void ReadXml(XmlReader reader) {
var att = reader.GetAttribute("LaunchVector");
var values = att.Split(',');
LaunchVector = new Vector {X = int.Parse(values[0]), Y = int.Parse(values[1])};
// deserialize other members
}

public void WriteXml(XmlWriter writer) {
writer.WriteAttributeString("LaunchVector", string.Format("{0},{1}", LaunchVector.X, LaunchVector.Y));
// serialize other membets
}
}



b) Or you can create a helper property of type string that does the conversion from and to string representation:


[XmlIgnore]
public Vector LaunchVector { get; set; }

[XmlAttribute("LaunchVector")]
public string LaunchVectorInternal {
get { return string.Format("{0},{1}", LaunchVector.X, LaunchVector.Y); }
set {
var values = value.Split(',');
LaunchVector = new Vector {X = int.Parse(values[0]), Y = int.Parse(values[1])};
}
}



Note how the original LaunchVector property is ignored.

Share this post


Link to post
Share on other sites
Crehl    134
Quote:
Original post by theOcelot
First solution off the top of my head is to get the vector as a string and parse it yourself. String constructor for vector class? It wouldn't be bad if you used a std::istringstream (or strstream, I always forget).


Quote:
Original post by VizOne
b) Or you can create a helper property of type string that does the conversion from and to string representation:


Thanks to both replies, I ended up with using an additional string property because it saves me having to write code to (de)serialize the rest of the class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this