“InvalidCastException:无法从源类型转换为目标类型。”加载序列化数据时

时间:2015-05-12 13:44:49

标签: c# serialization save loading

如果您查看了我的一些代码,我真的很感激,因为我似乎无法自己修复它,这也有望帮助其他人更好地理解序列化。

我这里有四条相关代码,其中任何看似无关紧要的内容都被删除了。我正在尝试在设置中创建用户个人资料,然后用户可以从一系列游戏中进行选择。仅保存所选游戏的选项/设置,在这种情况下与鱼有关。

标题中的错误发生在第4部分[随意跳到那个],这是

的OptionsController.LoadOptions()函数
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;

    }   
}

2)鱼类数据结构:

 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>();
    }

}

3)最初创建数据文件的脚本以及似乎没有问题的地方:

public class ProfileController : MonoBehaviour {


    public static string currentID;

    //create ----
    public InputField idField;
    public InputField nameField;
    public InputField dobField;
    public Toggle fishToggle;
    public Toggle birdToggle;

    //open ------
    public Button idTitleButton;
    public Text nameText;
    public Text dobText;

    public Text testText;
    public InputField numField;



    void Save() { //saves new ID and declares required variables based on game choice

        Debug.Log("id =" + idField.text + ", name = " + nameField.text + ", save");
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/" + idField.text + ".dat");

        Profile.Store data = new Profile.Store();                 //sets Profile variables

        currentID = idField.text;

        data.id = idField.text;
        data.name = nameField.text;
        data.dob = dobField.text;
        data.fishEnabled = fishToggle.isOn;
        data.birdEnabled = birdToggle.isOn;

        Profile.id = idField.text;
        Profile.name = nameField.text;
        Profile.dob = dobField.text;
        Profile.fishEnabled = fishToggle.isOn;
        Profile.birdEnabled = birdToggle.isOn;



        bf.Serialize(file, data);                            //saves Profile variables

        if (fishToggle.isOn) {
            FishData.Store dataFish = new FishData.Store();              //sets default Fish variables

            dataFish.sizeInc = false;
            dataFish.speedInc = false;
            dataFish.level = 5;
            dataFish.toxic = true;
            dataFish.handLeft = false;

            dataFish.timer = false;
            dataFish.timerVal = 240;
            dataFish.percentReq = 0;
            dataFish.successReq = 0;

            bf.Serialize(file, dataFish);                   //saves default Fish variables

            Debug.Log("level = " + dataFish.level);



        }

        file.Close();                                         //closes save file

        idSelectField.text = idField.text;          //ensures current ID is used as selected ID where needed
        EnableOpenProfile();                                   //loads new profile

    }


    void Load() {


        if (File.Exists(Application.persistentDataPath + "/" + idField.text + ".dat")) {  //loads save file
            currentID = idField.text;
            BinaryFormatter bf = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/" + idField.text + ".dat", FileMode.Open);
            Profile.Store data = (Profile.Store)bf.Deserialize(file);

            nameField.text = data.name;                             //loads saved Profile details and settings
            fishToggle.isOn = data.fishEnabled;
            birdToggle.isOn = data.birdEnabled;

            fishPlayButton.enabled = data.fishEnabled;
            birdPlayButton.enabled = data.birdEnabled;


            FishData.Store dataFish = (FishData.Store)bf.Deserialize(file);     //loads saved Fish settings
            FishData.sizeInc = dataFish.sizeInc;
            FishData.speedInc = dataFish.speedInc;
            FishData.toxic = dataFish.toxic;
            FishData.timer = dataFish.timer;
            FishData.level = dataFish.level;
            FishData.timerVal = dataFish.timerVal;
            FishData.percentReq = dataFish.percentReq;
            FishData.successReq = dataFish.successReq;
            FishData.handLeft = dataFish.handLeft;



            file.Close();                                           //closes save file


            nameText.text = "Name : " + data.name + "     ID : " + data.id;     //displays profile details
            dobText.text = "DOB : " + data.dob;


        }
        else return;
    }

}

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();

    }

}

谢谢。

2 个答案:

答案 0 :(得分:0)

如果我错了,请纠正我,但似乎您首先保存了Profile.Store 然后你保存FishData.Store。

然后在加载时,当Profile.Store首先在文件中时,你试图检索FishData.Store。

(我假设您使用脚本4中的加载和脚本3中的保存。)

答案 1 :(得分:0)

为确保您按正确的顺序序列化/反序列化,最好创建一个&#34; hold&#34;包含Fish.Store变量和Profile.Store变量的类。如果您使用不同的顺序进行序列化和取消序列化,则会遇到类似尝试将Fish.Store对象反序列化为Profile.Store的问题。

尝试创建另一个公共变量为Fish.StoreProfile.Store的类,例如:

public class ExampleClass
{
    public Fish.Store FishStore;
    public Profile.Store ProfileStore;

    public ExampleClass()
    {
    }
}

然后做:

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;

如果您只希望一次序列化/反序列化一个类,最佳做法是对每个序列化类的一个文件进行读/写。