The first time I learned you could
save fully saturated objects to a file and re-load them with a simple function call, I was stunned.
I couldn't believe it could be
that easy, especially with
php, which I was using at the time.
But, like many things, once you learn a concept in one language, you realize that many other languages support it as well.
Here's an example of
Xml Serialization in C#, supported in the namespace
System.Xml.Serialization. There's also
Binary Serialization which is much faster.
In this example, I created a simple game board, played a few moves, and serialized the game object. I then loaded it back up from the file, and -- voila! -- it's an instance of the object with all properties set and ready to go, just where I left them.
(The game board is just as example of a serialized object: there's no code for winning, checking moves, etc. - that's not the point, so please, no comments about it not telling you that you won!)
A couple caveats about serialization:
- You need a default constructor on the object you want serialized
- You need to mark your class [Serializable]
- Serialization of multi-dimensional arrays is not supported
- Anything you want serialized, you need both get and set properties
- Don't expect serialization to save anything you have going on in your object internally: it invokes the public properties for serialization, and deserialized by setting them back
The first board was created in code. The second board was pulled right out of the serialized object, fully intact.
Main class:
//gmcs Game.cs Main.cs /out:Main.exe
using System;
using System.IO;
using System.Xml.Serialization;
namespace rootsilver.serialization{
public class Test{
public static void Main(){
Console.WriteLine("Starting new game ...");
Game game = new Game();
game.BoardSize = 3;
game.Move(1, 1, "X");
game.Move(2, 2, "O");
game.Move(3, 3, "X");
game.Move(3, 1, "O");
game.Move(1, 3, "O");
game.PrintBoard();
Console.WriteLine();
Console.WriteLine("Saving game (serializing to file) ...");
string savedGameFile = SaveGame(game);
Console.WriteLine("Loading saved game (deserializing from file) ...");
Console.WriteLine();
Game game2 = LoadGame(savedGameFile);
game2.PrintBoard();
}
public static Game LoadGame(string filePath) {
Game game = null;
using (Stream stream = File.Open(filePath, FileMode.Open)) {
XmlSerializer serializer = new XmlSerializer(typeof(Game));
game = (Game)serializer.Deserialize(stream);
}
return game;
}
public static String SaveGame(Game game) {
string filePath = typeof(Game).ToString() + ".xml";
using (Stream stream = File.Open(filePath, FileMode.Create)) {
XmlSerializer serializer = new XmlSerializer(typeof(Game));
serializer.Serialize(stream, game);
}
return filePath;
}
}
}
... And the class that's being serialized to XML:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace rootsilver.serialization{
[Serializable]
public class Game{
//(multi-dimensional arrays can not be serialized)
private String[] board;
private int boardWidth;
private int boardSquareCount;
//xml serialization requires a default constructor
public Game() { }
public int BoardSize{
get {
return this.boardWidth;
}
set {
this.boardWidth = value;
this.boardSquareCount = boardWidth * boardWidth;
this.board = new String[this.boardSquareCount];
this.InitializeBoard(".");
}
}
public String[] Board{
get { return board; }
//set will get called by the deserializer
set { this.board = value; }
}
private void InitializeBoard(string defaultValue){
for(int i = 0; i < this.boardSquareCount; i++){
this.board[i] = defaultValue;
}
}
public void Move(int x, int y, string move){
--x;
--y;
int square = x + ( y + (y * (this.boardWidth - 1)));
this.board[square] = move;
}
public void PrintBoard(){
Console.WriteLine("---------");
for(int i = 0; i < this.boardSquareCount; i++){
if(i > 0 && (i % this.boardWidth == 0) )
Console.WriteLine();
Console.Write(this.board[i] + " ");
}
Console.WriteLine();
Console.WriteLine("---------");
}
}
}
Here's the XML created "for free" by the serialization:
<?xml version="1.0" encoding="utf-8"?>
<Game xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BoardSize>3</BoardSize>
<Board>
<string>X</string>
<string>.</string>
<string>O</string>
<string>.</string>
<string>O</string>
<string>.</string>
<string>O</string>
<string>.</string>
<string>X</string>
</Board>
</Game>