C# 加载序列化数据时,“InvalidCastException:无法从源类型强制转换为目标类型。”
如果您仔细阅读了我的一些代码,我将不胜感激,因为我自己似乎无法修复它,这也将有助于其他人更好地理解序列化 我这里有四段相关的代码,任何看似无关的东西都被删掉了。我试图在一个设置中创建一个用户配置文件,用户可以从一系列游戏中进行选择。仅保存所选游戏的选项/设置,在本例中与鱼有关 标题中的错误出现在第四节[请跳到该节],该节是位于的optionController.LoadOptions函数C# 加载序列化数据时,“InvalidCastException:无法从源类型强制转换为目标类型。”,c#,serialization,save,loading,C#,Serialization,Save,Loading,如果您仔细阅读了我的一些代码,我将不胜感激,因为我自己似乎无法修复它,这也将有助于其他人更好地理解序列化 我这里有四段相关的代码,任何看似无关的东西都被删掉了。我试图在一个设置中创建一个用户配置文件,用户可以从一系列游戏中进行选择。仅保存所选游戏的选项/设置,在本例中与鱼有关 标题中的错误出现在第四节[请跳到该节],该节是位于的optionController.LoadOptions函数 FishData.Store data = (FishData.Store)bf.Deserialize(f
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt);
我在以下所有章节的顶部都有这一点:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
1配置文件数据结构:
public class Profile { //Profile variables
public static string id;
public static string name;
public static string dob;
public static bool fishEnabled;
public static bool birdEnabled;
public static string stringTest;
[System.Serializable]
public class Store { //Profile variables
public string id;
public string name;
public string dob;
public bool fishEnabled;
public bool birdEnabled;
public string stringTest;
}
}
public class FishData { //static Fish variables to be used in game
public static bool sizeInc;
public static bool speedInc;
public static int level;
public static bool toxic;
public static bool handLeft;
public static bool timer;
public static int timerVal;
public static int percentReq;
public static int successReq;
public static string testStringTwo;
public static List<StatController.Session> sessions = new List<StatController.Session>();
[System.Serializable]
public class Store { //non static variable set for serialization
public bool sizeInc;
public bool speedInc;
public int level;
public bool toxic;
public bool handLeft;
public bool timer;
public int timerVal;
public int percentReq;
public int successReq;
public string testStringTwo;
public List<StatController.Session> sessions = new List<StatController.Session>();
}
}
2.Fish数据结构:
public class Profile { //Profile variables
public static string id;
public static string name;
public static string dob;
public static bool fishEnabled;
public static bool birdEnabled;
public static string stringTest;
[System.Serializable]
public class Store { //Profile variables
public string id;
public string name;
public string dob;
public bool fishEnabled;
public bool birdEnabled;
public string stringTest;
}
}
public class FishData { //static Fish variables to be used in game
public static bool sizeInc;
public static bool speedInc;
public static int level;
public static bool toxic;
public static bool handLeft;
public static bool timer;
public static int timerVal;
public static int percentReq;
public static int successReq;
public static string testStringTwo;
public static List<StatController.Session> sessions = new List<StatController.Session>();
[System.Serializable]
public class Store { //non static variable set for serialization
public bool sizeInc;
public bool speedInc;
public int level;
public bool toxic;
public bool handLeft;
public bool timer;
public int timerVal;
public int percentReq;
public int successReq;
public string testStringTwo;
public List<StatController.Session> sessions = new List<StatController.Session>();
}
}
4尝试加载上一个脚本中保存的内容时产生错误的主脚本:
public class OptionsController : MonoBehaviour {
public static bool handLeft = false;
public Toggle sizeIncToggle;
public Toggle speedIncToggle;
public Toggle toxicToggle;
public Toggle timerToggle;
public Toggle leftToggle;
public Toggle rightToggle;
public InputField levelField;
public InputField timerValField;
public InputField percentReqField;
public InputField successReqField;
void LoadOptions() {
if (File.Exists(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileOpt = File.Open(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat", FileMode.Open);
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt); //[[ERROR HERE]]
sizeIncToggle.isOn = data.sizeInc;
speedIncToggle.isOn = data.speedInc;
toxicToggle.isOn = data.toxic;
timerToggle.isOn = data.timer;
levelField.text = data.level.ToString();
timerValField.text = data.timerVal.ToString();
percentReqField.text = data.percentReq.ToString();
successReqField.text = data.successReq.ToString();
fileOpt.Close();
}
}
public void SaveOptions() {
Debug.Log("name = " + ProfileController.currentID + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat");
FishData.Store data = new FishData.Store();
data.sizeInc = FishData.sizeInc;
data.speedInc = FishData.speedInc;
data.toxic = FishData.toxic;
data.timer = FishData.timer;
data.level = FishData.level;
data.timerVal = FishData.timerVal;
data.percentReq = FishData.percentReq;
data.successReq = FishData.successReq;
data.handLeft = FishData.handLeft;
bf.Serialize(file, data);
Debug.Log("level = " + FishData.level);
file.Close();
}
}
谢谢。如果我错了,请纠正我,但似乎您首先保存了Profile.Store 然后保存FishData.Store 然后在加载时,当Profile.Store位于文件的第一个位置时,尝试检索FishData.Store
我假设您使用脚本4中的加载和脚本3中的保存。为了确保以正确的顺序序列化/反序列化,最好创建一个包含Fish.Store变量和Profile.Store变量的保持类。如果以不同的顺序序列化和反序列化,您将遇到一些问题,例如尝试将Fish.Store对象反序列化到Profile.Store 尝试使用Fish.Store和Profile.Store的公共变量创建另一个类,如: 然后做:
ExampleClass example = new ExampleClass();
example.ProfileStore = data;
example.FishStore = dataFish;
//File Create stuff, etc
bf.Serialize(file, example);
//File close stuff, etc
以及反序列化:
ExampleClass e = (ExampleClass)bf.Deserialize(fileOpt);
data = e.ProfileStore;
dataFish = e.FishStore;
如果您只希望一次序列化/反序列化一个类,那么最好的做法是对每个序列化的类从一个文件读/写。Profile.Store和FishData.Store实际上都是通过脚本3保存到文件中的。我已经通过检查文本文件手动检查了这一点——尽管由于序列化,格式混乱,但我可以清楚地看到来自两个文件的变量。您能推荐一种更好的方法将不同类型的数据保存和加载到一个文件中吗?这是一种可行的方法,您只需确保加载对象的顺序与保存对象的顺序相同,在本例中,首先是配置文件,然后是数据。在检索fisdata时,实际上是在检索序列化的profiledata。如果您不想/不需要加载profiledata,可以将其保存在单独的文件中。就像fishdata+currentID一样。你也可以引用你的fishdata.Store作为ProfileData.Store的一个成员,因为它们应该同时被序列化,并且fishdata是可序列化的,那么只需将整个文件反序列化为ProfileData.Store对象.Casper-哦,天哪,这太简单了。非常感谢你。我在代码的初始问题行之前添加了这个:Profile.storedataprof=Profile.Storebf.DeserializefileOpt;这是否意味着在保存时,即使我没有更改任何变量,也必须按顺序序列化不同的数据类型?谢谢,这很有用。我可以知道为什么FishStore和ProfileStore一开始就被资本化了吗?类的实例不应该像example和e那样用小写字母声明吗?我看不出有什么不同。因为我打字很快,坦白说,这不重要,它仍然有效。你不会把这个类叫做ExampleClass,它只是一个例子,你想怎么叫就怎么叫吧。我明白了。使用您的方法,我是否能够在不影响ProfileStore的情况下在FishStore multilpe时间内重新保存数据?因为我刚才只是通过简单地添加Profile.storedataprof=newprofile.Store来测试按顺序序列化和反序列化这两种类型;序列化文件,dataProf;FishData.Store数据之前=新建FishData.Store;在脚本4中。在我看到配置文件变量现在为空并且需要在我添加的两行之间重新初始化之前,这似乎工作得很好。ExampleClass将始终具有Fish.Store和profile.Store的变量。在序列化之前,它们始终需要是正确的当前值。不要单独序列化这两个类。仅序列化持有ExampleClass。