简体   繁体   English

XmlSerializer.Deserialize() 似乎不起作用

[英]XmlSerializer.Deserialize() Does not appear to work

I'm able to successfully serialize and save data in XML UTF-8 format as far as I can tell but, I am not able to deserialize that very same data.据我所知,我能够以 XML UTF-8 格式成功序列化和保存数据,但是,我无法反序列化相同的数据。

I've tried researching this problem but, nobody seems to have the same issue of just deserialization not working.我试过研究这个问题,但是,似乎没有人有同样的问题,只是反序列化不起作用。 That's what I believe to be the problem at least.这就是我认为至少是问题所在。

    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
    }

When I use the SaveItemsUTF method, it successfully produces a file with the test data in the correct format in the correct location which can be seen here: https://imgur.com/a/5PJMTRh当我使用 SaveItemsUTF 方法时,它成功地在正确的位置生成了一个包含正确格式的测试数据的文件,可以在此处看到: https://imgur.com/a/5PJMTRh

However, when I use the LoadItems method, nothing appears to happen.但是,当我使用 LoadItems 方法时,似乎什么也没发生。 No errors or logs in the console.控制台中没有错误或日志。 No data gets loaded.没有数据被加载。 It appears to do nothing.它似乎什么也没做。 I am officially stuck.我被正式卡住了。

It is deserialized.它是反序列化的。 You can put breakpoint and see that element in LoadItems is filled with correct data.您可以放置断点并查看 LoadItems 中的元素填充了正确的数据。

But now the issue is about the way value/reference types work in .NET.但现在的问题是关于值/引用类型在 .NET 中的工作方式。 You cannot change the value (reassign reference, to which itemDB is pointint to in method; you can change data inside it though, but that's other topoic) from method, where it's used.您不能从使用它的方法更改值(重新分配引用,itemDB 在方法中指向哪个;您可以更改其中的数据,但这是其他主题) Strictly speaking, " object is passed to methods by reference, but the reference itself is passed by value; if you really need to reassign reference in method, use modifiers for that ".严格来说,“ object 是通过引用传递给方法的,而引用本身是通过值传递的;如果确实需要在方法中重新分配引用,请为此使用修饰符”。

So either use ref/out modifiers (as pointed by BrettCaswell in comments section, out is preferred; it's the way to say "content is passed by reference and will be reassigned inside", while ref means "content is passed by reference and might be reassigned inside"):所以要么使用 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);

or change to:或更改为:

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

.NET encapsulates TryParse approach to solve similar tasks of both parsing data and providing status for parse); .NET 封装了 TryParse 方法来解决解析数据和为解析提供状态的类似任务); here is example with integer (value type): https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=netframework-4.8这是 integer(值类型)的示例: https://docs.microsoft.com/en-us/dotnet/api/system.int32.tryparse?view=netframework-4.8

You can use generic type functions, it make your code reusable for other object types.您可以使用泛型类型函数,它使您的代码可重用于其他 object 类型。 I can not check my code, so maybe it can give some error.我无法检查我的代码,所以它可能会出现一些错误。

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

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

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