繁体   English   中英

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

[英]“InvalidCastException: Cannot cast from source type to destination type.” when loading serialized data

如果您仔细阅读了我的一些代码,我将不胜感激,因为我似乎无法自己修复它,这也有望帮助其他人更好地理解序列化。

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

标题中的错误发生在第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();

    }

}

谢谢。

如果我错了,请纠正我,但看来您先保存了Profile.Store,然后又保存了FishData.Store。

然后,在加载时,当Profile.Store首次出现在文件中时,您尝试检索FishData.Store。

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

为确保以正确的顺序进行序列化/反序列化,最好创建一个“持有”类,其中同时包含Fish.Store变量和Profile.Store变量。 如果以不同的顺序进行序列化和反序列化,则会遇到诸如尝试将Fish.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;

如果您一次只希望序列化/反序列化一个类,则最佳实践是为每个序列化的类读取/写入一个文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM