XmlSerializer.Deserialize () не работает - PullRequest
0 голосов
/ 30 октября 2019

Насколько я могу судить, я могу успешно сериализовать и сохранить данные в формате XML UTF-8, но я не могу десериализовать те же самые данные.

Я пытался исследовать этопроблема, но, кажется, ни у кого не возникает проблем с десериализацией. По крайней мере, я считаю, что это проблема.

    public static class XMLManager
    {
        //Save Function
        public static void SaveItemsUTF(ItemDatabase itemDB)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));
            string filename = Application.dataPath + "/StreamingFiles/XML/item_data.xml";
            Encoding encoding = Encoding.GetEncoding("UTF-8");

            using (StreamWriter stream = new StreamWriter(filename, false, encoding))
            {
                serializer.Serialize(stream, itemDB);
            }
        }

        //Load Function
        public static void LoadItems(ItemDatabase itemDB)
        {
            //Open an XML File
            if (File.Exists(Application.dataPath + "/StreamingFiles/XML/item_data.xml"))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ItemDatabase));
                FileStream stream = new FileStream(Application.dataPath + "/StreamingFiles/XML/item_data.xml", FileMode.Open);
                itemDB = serializer.Deserialize(stream) as ItemDatabase;
                stream.Close();
            }
            else
            {
                Debug.LogError("File not found!");
            }
        }

        //Delete Function
        public static void DeleteItems()
        {
            //Delete an XML File
            File.Delete(Application.dataPath + "/StreamingFiles/XML/item_data.xml");
        }
    }

    [System.Serializable]
    public class ItemEntry
    {
        public string ItemName;
        public SaveMaterial material;
        public int Value;
    }

    [System.Serializable]
    public class ItemDatabase
    {
        [XmlArray("CombatEquipment")]
        public List<ItemEntry> list = new List<ItemEntry>();
    }

    public enum SaveMaterial
    {
        Wood,
        Copper,
        Iron,
        Steel,
        Obsidian
    }

Когда я использую метод SaveItemsUTF, он успешно создает файл с тестовыми данными в правильном формате в правильном месте, которое можно увидеть здесь:https://imgur.com/a/5PJMTRh

Однако, когда я использую метод LoadItems, ничего не происходит. Никаких ошибок или логов в консоли. Данные не загружаются. Похоже, ничего не делать. Я официально застрял.

Ответы [ 2 ]

2 голосов
/ 30 октября 2019

десериализовано. Вы можете поставить точку останова и увидеть, что элемент в LoadItems заполнен правильными данными.

Но теперь проблема заключается в том, как работают значения / ссылочные типы в .NET. Вы не можете изменить значение (переназначить ссылку, на которую itemDB указывает pointint в методе; хотя вы можете изменить данные внутри него, но это другая топика) from метода, в котором он используется. Строго говоря, « объект передается методам по ссылке, но сама ссылка передается по значению; если вам действительно нужно переназначить ссылку в методе, используйте для этого модификаторы ».

Так что либо используйте модификаторы ref / out (как указано BrettCaswell в разделе комментариев, out предпочтительнее; это способ сказать «контент передается по ссылке, и будет переназначен внутри», в то время какref означает, что «содержимое передается по ссылке, и может быть переназначено внутри»):

public static void LoadItems(out ItemDatabase itemDB); // will work; but you'll call it as below, with out modifier: 
// XMLManager.LoadItems(out itemDBName);

или изменить на:

public static ItemDatabase LoadItems(); // also will work, but, of course, you'll need to  create ItemDatabase internally in LoadItems

.NET инкапсулирует подход TryParse крешить похожие задачи как разбора данных, так и предоставления статуса для разбора);Вот пример с целым числом (тип значения): https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=netframework-4.8

1 голос
/ 30 октября 2019

Вы можете использовать функции универсального типа, это делает ваш код многоразовым для других типов объектов. Я не могу проверить свой код, поэтому, возможно, он может дать какую-то ошибку.

static void Serialize<T>(T data, string path)
{
    FileStream fs = new FileStream(path, FileMode.Create);
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    serializer.Serialize(fs, data);
    fs.Close();
}


static T Deserialize<T>(string path)
{
    FileStream fs = new FileStream(path, FileMode.Open);
    XmlSerializer xs = new XmlSerializer(typeof(T));
    T obj = (T)xs.Deserialize(fs);
    fs.Close();
    return obj;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...