The most effective way to be 100% sure of saving and loading tile-based levels have, in my experience, to use BinaryWriter and BinaryReader.
Our level-structure has been a lot different from yours, though; We have many layers. Each layer uses a tileset and consists of instances of Tile. Tile holds its position (Vector2D) and a TileId (index of the tile in the tileset-texture).
The way we put objects in levels are with tilesets that are replaced by real objects on loading.
Anyways, a suitably generic way to save and load data is by letting your classes have a contructor that can take a BinaryReader as an argument, and a method to write itself to a BinaryWriter.
like this:
public Tile(BinaryReader reader)
{
Position.X = reader.ReadFloat();
Position.Y = reader.ReadFloat();
TileId = reader.ReadInt32();
}
public void WriteToStream(BinaryWriter writer)
{
writer.Write(Position.X);
writer.Write(Position.Y);
writer.Write(TileId);
}
if you only have one class to load, you can then simply:
for loading:
var tiles = new List<Tile>();
var reader = new BinaryReader(File.Open("level.bin"));
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
var tile = new Tile(reader);
tiles.Add(tile);
}
reader.Close();
For saving:
var tiles; //lets pretend this is the level
var writer = new BinaryWriter(File.Create("level.bin"));
foreach (var tile in tiles)
{
tile.WriteToStream(writer);
}
writer.Flush(); //IMPORTANT!!!
writer.Close();
If, however, your list contains items of different types, you need to store the type also. A pretty generic way to do this is by inserting:
writer.Write(tile.GetType().FullName);
before tile.WriteToStream(writer);
and then on loading you need to:
var tileType = Type.GetType(reader.ReadString()); //Read the type from the stream
var constructor = tileType.GetConstructor(new [] { typeof(BinaryReader)}); //get a constructor that can use a binaryreader
var tile = constructor.Invoke(new [] { reader }); //use said constructor to create an instance
Hope this helps. And note that I am writing this out of memory, so syntax errors are probable....