I've run into this interesting issue where I get an System.InvalidCastException: 'Specified cast is not valid.'
while trying to cast my object
inside my Dictionary<string, object>
to and (int)
. Inside this Dictionary I store state for the current Game someone is playing and want to re-save / re-load
the data if the game requires a save or has been closed. This method is only for reading the save not saving it.
Many Thanks in Advance.
Code:
public async Task ReadGameFileInAsync(string gameVersion)
{
var gameSave = new Dictionary<string, object>();
if (gameVersion == "bronze")
gameSave = JsonConvert.DeserializeObject<Dictionary<string, object>>(await ReadFileInAsync(BronzeGameSaveFilePath));
else if (gameVersion == "silver")
gameSave = JsonConvert.DeserializeObject<Dictionary<string, object>>(await ReadFileInAsync(SilverGameSaveFilePath));
_GameStats.CurrentGame = (int)gameSave["CurrentGame"]; //Error throws here.
_GameStats.CurrentWord = (int)gameSave["CurrentWord"];
_GameStats.Score = (int)gameSave["Score"];
_GameStats.BestScore = (int)gameSave["BestScore"];
_GameStats.Difficulty = (int)gameSave["Difficulty"];
_GameStats.IsNewGame = (bool)gameSave["IsNewGame"];
_GameStats.IsContinue = (bool)gameSave["IsContinue"];
_GameStats.IsUnlocked = (bool)gameSave["IsUnlocked"];
_GameStats.GameVersion = (string)gameSave["GameVersion"];
_GameStats.Cards = (ObservableCollection<LevelCardGroup>)gameSave["Cards"];
}
GameStats:
public class GameStats : IGameStats
{
public int CurrentGame { get; set; } = 1;
public int CurrentWord { get; set; } = 1;
public int Score { get; set; } = 0;
public int BestScore { get; set; } = 0;
public bool IsNewGame { get; set; } = true;
public bool IsContinue { get; set; } = false;
public bool IsUnlocked { get; set; } = false;
public bool ContinueButtonPressed { get; set; } = false;
public string GameVersion { get; set; } = string.Empty;
public int Difficulty { get; set; } = 3;
public ObservableCollection<LevelCardGroup> Cards { get; set; } = new ObservableCollection<LevelCardGroup>();
public void ResetGameStats(string gameVersion = "")
{
CurrentGame = 1;
CurrentWord = 1;
Score = 0;
BestScore = 0;
IsNewGame = true;
IsContinue = false;
GameVersion = gameVersion;
Difficulty = 3;
Cards.Clear();
}
}
Just deserialize to the class instance and copy data from it:
public async Task ReadGameFileInAsync(string gameVersion)
{
var gameSave = gameVersion switch
{
"bronze" => JsonConvert.DeserializeObject<GameStats>(await ReadFileInAsync(BronzeGameSaveFilePath)),
"silver" => JsonConvert.DeserializeObject<GameStats>(await ReadFileInAsync(SilverGameSaveFilePath)),
_ => null
};
if (gameSave is not null)
{
_GameStats.CurrentGame = gameSave.CurrentGame; // or maybe better create a copy from method
// ...
}
else
{
// todo: throw? clear game stats?
}
}