如何在XML中保存对象实例的引用

时间:2013-11-25 16:45:52

标签: c# xml save

修改: 得到了答案,我将播放器中的Inv列表更改为int列表,并将游戏初始加载时的项目导入到字典中,如下所示:

public static class InitLoad
{
    static List<ItemEquipmentWeapon> weapons;

    public static Dictionary<int, Item> ItemIDList = new Dictionary<int, Item>();

    public static void PreLoading()
    {

        string path, filePath, 
            weaponFile = @"\WeaponsItem.aid";
        XmlSerializer SerializerObj;
        FileStream ReadFileStream;

        path = string.Format(@"{0}\AwesomeRPG\Data\Items",
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
        filePath = string.Format(@"{0}\{1}", path, weaponFile);
        SerializerObj = new XmlSerializer(typeof(ItemEquipmentWeapon));
        ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
        weapons = (List<ItemEquipmentWeapon>)SerializerObj.Deserialize(ReadFileStream);
        foreach (Item item in weapons)
        {
            ItemIDList.Add(item.ID, item);
        }
    }
}

意思是我可以用我的玩家类做到这一点:

[Serializable()]
public class Player : Entity
{
    public string Name { get; set; }
    public int MaxHP { get; set; }
    public int Level { get; set; }
    public int XP { get; set; }
    public int Str { get; set; }
    public int End { get; set; }
    public int Dex { get; set; }
    public int Agi { get; set; }
    public int Wis { get; set; }
    public int Int { get; set; }
    //Create a list of Item Id's for inventory
    public List<int> Inv { get; set; }

    private int lHand;
    private int rHand;

    public int LHand
    {
        get 
        { return lHand; }
        set
        {
            if (!value.THand)
            {
                lHand = value;
            }
            else lHand = null;
        }
    }
    public int RHand
    {
        get 
        { return rHand; }
        set 
        { rHand = value; }
    }

    internal Player() { }
    public Player(string name, int maxhp, int hp, int lvl, int exp, int str, int end, int dex, int agi, int wis, int inte)
        : base(true, hp)
    {
        Name = name;
        MaxHP = maxhp;
        Level = lvl;
        XP = exp;
        Str = str;
        End = end;
        Dex = dex;
        Agi = agi;
        Wis = wis;
        Int = inte;

        Inv = new List<int>();
    }

    public List<string> GetInv()
    {
        List<string> val = new List<string>();
        Item item;
        foreach (int i in Inv)
        {
            InitLoad.ItemIDList.TryGetValue(i, out item);
            val.Add(item.Name);
        }

        return val;
    }

    public void AddItem(Item i, int amt)
    {
        for (int j = 0; j < amt; j++)
        {
            Inv.Add(i.ID);
        }
    }
    public void AddItem(Item i){
        AddItem(i, 1); }

    public void RemoveItem(Item i, int amt)
    {
        int count = 0;

        foreach (int item in Inv)
        {
            if (item == i.ID)
            {
                Inv.Remove(item);
                count++;
            }
            if (count == amt)
            {
                break;
            }
        }
    }
    public void RemoveItem(Item i){
        RemoveItem(i, 1); }

    public bool HasItem(Item i, int amt)
    {
        int count = 0;

        foreach (int item in Inv)
        {
            if (item == i.ID)
            {
                count++;
            }
        }

        return count >= amt;
    }
    public bool HasItem(Item i){
        return HasItem(i, 1); }
}

希望这可以帮助其他人!

原始问题:

所以,我正在制作一个愚蠢的小型RPG游戏,用Windows窗体来测试我的技能,而且我正在整理保存。目前它保存到XML文件,该文件是自定义扩展名(.asd) 这是我的保存/加载代码:

public static class SaveGame
{
    public static void Save(Player player)
    {
        string myfile = string.Format(@"{1}\AwesomeRPG\Saves\{0}Save.asd", player.Name, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
        //Delete file if it already exists
        if (File.Exists(myfile)) System.IO.File.Delete(myfile);
        //Create/Write to the file
        FileStream outFile = File.Create(myfile);            
        XmlSerializer Serializer = new XmlSerializer(typeof(Player));
        Serializer.Serialize(outFile, player);
        outFile.Close();
    }

    public static Player Load(string FileName)
    {
        string myfile = string.Format(@"{1}\AwesomeRPG\Saves\{0}Save.asd", FileName, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

        if (!File.Exists(myfile)) return null;
        XmlSerializer Serializer = new XmlSerializer(typeof(Player));
        FileStream ReadFileStream = new FileStream(myfile, FileMode.Open, FileAccess.Read, FileShare.Read);
        return (Player)Serializer.Deserialize(ReadFileStream);
    }
}

可以想象,这会保存Inv列表中任何项目的所有细节。 但是,我希望在游戏开始时加载所有存在的项目(创建它们的实例),并且我需要一种方法让保存文件保存对这些实例的引用,而不是创建新实例。

游戏开始时加载的实例也保存在XML文件中,然后根据项类型加载到单独的列表中,例如,所有ItemEquipmentWeapon实例(继承项继续Item的ItemEquipment)都在WeaponItem.aid文件中,这是以XML格式,并加载到List

有什么方法可以通过引用保存和加载来自播放器保存文件的Inv内容,这样我可以让它们在初始加载时使用现有的实例设置吗?

编辑: 想一想,看看Player类是如何编码的,可能会有所帮助,所以这就是:

[Serializable()]
public class Player : Entity
{
    public string Name { get; set; }
    public int MaxHP { get; set; }
    public int Level { get; set; }
    public int XP { get; set; }
    public int Str { get; set; }
    public int End { get; set; }
    public int Dex { get; set; }
    public int Agi { get; set; }
    public int Wis { get; set; }
    public int Int { get; set; }

    public List<Item> Inv { get; set; }

    private ItemEquipmentWeapon lHand;
    private ItemEquipmentWeapon rHand;

    public ItemEquipmentWeapon LHand
    {
        get 
        { return lHand; }
        set
        {
            if (!value.THand)
            {
                lHand = value;
            }
            else lHand = null;
        }
    }
    public ItemEquipmentWeapon RHand
    {
        get 
        { return rHand; }
        set 
        { rHand = value; }
    }

    internal Player() { }
    public Player(string name, int maxhp, int hp, int lvl, int exp, int str, int end, int dex, int agi, int wis, int inte)
        : base(true, hp)
    {
        Name = name;
        MaxHP = maxhp;
        Level = lvl;
        XP = exp;
        Str = str;
        End = end;
        Dex = dex;
        Agi = agi;
        Wis = wis;
        Int = inte;

        Inv = new List<Item>();
    }

    public List<string> GetInv()
    {
        List<string> val = new List<string>();

        foreach (Item item in Inv)
        {
            val.Add(item.Name);
        }

        return val;
    }

    public void AddItem(Item i, int amt)
    {
        for (int j = 0; j < amt; j++)
        {
            Inv.Add(i);
        }
    }
    public void AddItem(Item i){
        AddItem(i, 1); }

    public void RemoveItem(Item i, int amt)
    {
        int count = 0;

        foreach (Item item in Inv)
        {
            if (item == i)
            {
                Inv.Remove(item);
                count++;
            }
            if (count == amt)
            {
                break;
            }
        }
    }
    public void RemoveItem(Item i){
        RemoveItem(i, 1); }

    public bool HasItem(Item i, int amt)
    {
        int count = 0;

        foreach (Item item in Inv)
        {
            if (item == i)
            {
                count++;
            }
        }

        return count >= amt;
    }
    public bool HasItem(Item i){
        return HasItem(i, 1); }
}

显然,在游戏加载时从XML加载项目实例的代码也非常有用,但我还没编码,我不是100%肯定我会怎么做。 到目前为止,我有这个:

public static class InitLoad
{
    static List<ItemEquipmentWeapon> weapons;

    public static void PreLoading()
    {
        string path, filePath, 
            weaponFile = @"\WeaponsItem.aid";
        XmlSerializer SerializerObj;
        FileStream ReadFileStream;

        path = string.Format(@"{0}\AwesomeRPG\Data\Items",
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));

        filePath = string.Format(@"{0}\{1}", path, weaponFile);
        SerializerObj = new XmlSerializer(typeof(ItemEquipmentWeapon));
        ReadFileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
        weapons = (List<ItemEquipmentWeapon>)SerializerObj.Deserialize(ReadFileStream);
    }
}

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

  

有什么方法可以通过引用保存和加载来自播放器保存文件的Inv内容,这样我可以让它们在初始加载时使用现有的实例设置吗?

以下是解决此问题的一种方法:
1.添加到您的Item课程int字段Id或类似内容,并为每个唯一项目指定适当的唯一值。
2.在初始加载期间,创建游戏中所有唯一项目的全局缓存。对于这个问题,我建议使用Dictionary<int, Item>,其中项的关键字为Id,值为项目本身。
3.在Player类中,您应该只存储Id个项目,因此在加载期间,您可以从前面提到的全局缓存中获取Item的实例。

此外,您可能希望了解flyweight模式,这几乎与共享实例有关。