XMLSerializer正确序列化,但在反序列化时抛出TargetInvocationException

时间:2015-02-07 15:39:44

标签: c# xml unity3d mono xml-serialization

我正在为Unity游戏制作库存系统。

按预期方式将库存序列化并保存到xml文件中;但是,当我反序列化时,项目被设置为null并抛出 TargetInvocationException ;最后是 NullReferenceException


我做错了什么?


序列化和反序列化方法

public void SaveInventoryToXML()
{
    System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof (List<Item>));
    System.IO.StreamWriter file = new System.IO.StreamWriter(inventoryPath);
    writer.Serialize(file, inventory);
    file.Close();
}

public void LoadInventoryFromXML()
{
    System.Xml.Serialization.XmlSerializer reader = new System.Xml.Serialization.XmlSerializer(typeof(List<Item>));
    StreamReader sr = new StreamReader(inventoryPath);
    inventory = (List<Item>) reader.Deserialize(sr);
    sr.Close();
}

'项目'&amp; '结界'等级

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

[System.Serializable] //what's with the square brackets
public class Item
{
    public string ItemName;
    public int ItemId;
    public string ItemDesc;
    public int BaseWorth;
    public int BaseDamage;
    public int RequiredLevel;
    public Sprite Sprite;
    public ItemType itemType;
    public ItemRarity itemRarity;
    public Weapon.WeaponType weaponType;
    public Weapon.AttackType attackType;
    public List<Enchantment> Enchantments;
    public bool Stackable;
    public int StackSize = 99;
    public int Amount = 1;

    public enum ItemType
    {
        Weapon, Consumable, Quest, Armor, Boots, Helmet, Gloves, Ring, Amulet
    }

    public enum ItemRarity
    {
        Common, Rare, Unique, Magic
    }

    public Item(string name, int id, int reqlvl, string desc, int baseworth, int basedamage, List<Enchantment> enchantments, ItemType itemtype, ItemRarity itemrarity, Sprite sprite )
    {
        ItemName = name;
        ItemId = id;
        RequiredLevel = reqlvl;
        ItemDesc = desc;
        BaseWorth = baseworth;
        BaseDamage = basedamage;
        Enchantments = enchantments;
        itemType = itemtype;
        itemRarity = itemrarity;
        Sprite = sprite;
        additionalParameters();
    }

    private void additionalParameters()
    {
        switch (itemType)
        {
            case ItemType.Consumable:
                Stackable = true;
                break;
        }
    }

    public Item()
    {
        ItemId = -1;
    }
}

public class Enchantment
{
    public EnchantmentType Type;
    public int Amount;
    public enum EnchantmentType
    {
        Fire, Ice, Poison, Electric, Brutalize, Greed, Invisiblity, Heal, ReplenishStamina, ReplenishMana,
        AddMaxHealth, AddMaxStamina, AddMaxMana
    }

    public Enchantment(EnchantmentType type, int amount)
    {
        Amount = amount;
        Type = type;
    }

    public Enchantment()
    {

    }
}

调用堆栈

NullReferenceException
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:222)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoMethod.cs:232)
System.Reflection.MonoProperty.SetValue (System.Object obj, System.Object value, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] index, System.Globalization.CultureInfo culture) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/MonoProperty.cs:348)
System.Reflection.PropertyInfo.SetValue (System.Object obj, System.Object value, System.Object[] index) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/PropertyInfo.cs:102)
System.Xml.Serialization.XmlTypeMapMember.SetValue (System.Object ob, System.Object value)
System.Xml.Serialization.XmlSerializationReaderInterpreter.SetMemberValue (System.Xml.Serialization.XmlTypeMapMember member, System.Object ob, System.Object value, Boolean isValueList)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadMembers (System.Xml.Serialization.ClassMap map, System.Object ob, Boolean isValueList, Boolean readByOrder)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstanceMembers (System.Xml.Serialization.XmlTypeMapping typeMap, System.Object ob)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstance (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObject (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObjectElement (System.Xml.Serialization.XmlTypeMapElementInfo elem)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadMembers (System.Xml.Serialization.ClassMap map, System.Object ob, Boolean isValueList, Boolean readByOrder)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstanceMembers (System.Xml.Serialization.XmlTypeMapping typeMap, System.Object ob)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadClassInstance (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObject (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObjectElement (System.Xml.Serialization.XmlTypeMapElementInfo elem)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadListElement (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, System.Object list, Boolean canCreateInstance)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadObject (System.Xml.Serialization.XmlTypeMapping typeMap, Boolean isNullable, Boolean checkType)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot (System.Xml.Serialization.XmlTypeMapping rootMap)
System.Xml.Serialization.XmlSerializationReaderInterpreter.ReadRoot ()
System.Xml.Serialization.XmlSerializer.Deserialize (System.Xml.Serialization.XmlSerializationReader reader)

writer.Serializer

采样 输出

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Item>
        <ItemName>Steel Sword</ItemName>
        <ItemId>102</ItemId>
        <ItemDesc>A fine steel sword.</ItemDesc>
        <BaseWorth>125</BaseWorth>
        <BaseDamage>25</BaseDamage>
        <RequiredLevel>10</RequiredLevel>
        <Sprite>
            <name>BasicWeapons_2</name>
            <hideFlags>NotEditable</hideFlags>
        </Sprite>
        <itemType>Weapon</itemType>
        <itemRarity>Rare</itemRarity>
        <weaponType>Sword</weaponType>
        <attackType>Swing</attackType>
        <Stackable>false</Stackable>
        <StackSize>99</StackSize>
        <Amount>1</Amount>
    </Item>
    <Item>
        <ItemName>Mithril Sword</ItemName>
        <ItemId>103</ItemId>
        <ItemDesc>Feels lighter than steel, yet much sharper...</ItemDesc>
        <BaseWorth>625</BaseWorth>
        <BaseDamage>125</BaseDamage>
        <RequiredLevel>25</RequiredLevel>
        <Sprite>
            <name>BasicWeapons_3</name>
            <hideFlags>NotEditable</hideFlags>
        </Sprite>
        <itemType>Weapon</itemType>
        <itemRarity>Unique</itemRarity>
        <weaponType>Sword</weaponType>
        <attackType>Swing</attackType>
        <Stackable>false</Stackable>
        <StackSize>99</StackSize>
        <Amount>1</Amount>
    </Item>
    <Item>
        <ItemId>-1</ItemId>
        <BaseWorth>0</BaseWorth>
        <BaseDamage>0</BaseDamage>
        <RequiredLevel>0</RequiredLevel>
        <itemType>Weapon</itemType>
        <itemRarity>Common</itemRarity>
        <weaponType>Sword</weaponType>
        <attackType>Swing</attackType>
        <Stackable>false</Stackable>
        <StackSize>99</StackSize>
        <Amount>1</Amount>
    </Item>
</ArrayOfItem>

档案:http://a.pomf.se/avxuvz.xml

2 个答案:

答案 0 :(得分:2)

我刚刚尝试了您的代码,并设法通过删除Sprite字段使其正常工作。我的猜测是,这是你的罪魁祸首,因为它很可能无法序列化 - 所以你可能只需要将精灵的路径存储为string或类似的东西。

var list = new List<Item>()
{
    new Item(),
    new Item()
};
var xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(List<Item>));

using (var stream = File.Open("Document.xml", FileMode.CreateNew))
{
    xmlSerializer.Serialize(stream, list);
}

using (var stream = File.Open("Document.xml", FileMode.Open))
{
    xmlSerializer.Deserialize(stream);
}

产生以下输出:

<?xml version="1.0"?>
<ArrayOfItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Item>
    <ItemId>-1</ItemId>
    <BaseWorth>0</BaseWorth>
    <BaseDamage>0</BaseDamage>
    <RequiredLevel>0</RequiredLevel>
    <itemType>Weapon</itemType>
    <itemRarity>Common</itemRarity>
    <Stackable>false</Stackable>
    <StackSize>99</StackSize>
    <Amount>1</Amount>
  </Item>
  <Item>
    <ItemId>-1</ItemId>
    <BaseWorth>0</BaseWorth>
    <BaseDamage>0</BaseDamage>
    <RequiredLevel>0</RequiredLevel>
    <itemType>Weapon</itemType>
    <itemRarity>Common</itemRarity>
    <Stackable>false</Stackable>
    <StackSize>99</StackSize>
    <Amount>1</Amount>
  </Item>
</ArrayOfItem>

答案 1 :(得分:1)

显然手动执行操作并不好玩,但您可以尝试通过IXmlSerializable进行序列化。