首页 文章

在多个不同的类C#中使用XML来(解析?)元素

提问于
浏览
1

我真的很抱歉,如果答案存在于另一个名称,但我一直在试图解决这个问题一个星期左右,并没有找到类似的东西 .

所以,我正在为一个统一的游戏构建一个Item系统 . 有一个包含这些属性的Item类

public int ItemId;
public string ItemName;

为简单起见,假设我想要两个派生类,Weapon和Armor,其中包含Weapon的BaseDamage属性和Armor的BaseArmor .

我还想从XML加载ItemContainer类中的项目,理想情况下,从同一个XML文件而不是武器中加载一个项目,一个用于装甲,一个用于魔法 .

我尝试了多种方法,但到目前为止,我能够成功的唯一方法是将BaseDamage和BaseArmor添加到Item基类......像这样:

public class Item
{
    [XmlAttribute("ID")] public int ItemID;
    [XmlElement("Name")] public string ItemName;
    [XmlElement("Damage")] public int ItemBaseDamage;
    [XmlElement("Armor")] public int ItemBaseArmor;
}

并且根本不将元素添加到XML文件中以获取某些项:

<ItemCollection>
  <Items>

    <Item ID ="001">
      <Name>Dagger</Name>
      <Damage>10</Damage>
    </Item>

    <Item ID ="002">
      <Name>Chain Mail</Name>
      <Armor>5</Armor>
    </Item>

  </Items>
</ItemCollection>

它确实有效,但我觉得这不是正确的方法 . 另一个问题是,如果我想添加一个具有特定功能的Scroll类来强制转换写在该滚动上的咒语,我需要将“SpellToCast”属性添加到基类并向其添加一个CastSpell(Spell)函数从任何项目调用,这不是我想要的...

简而言之,我想从XML中加载多个项目,但每个项目都是其预期的派生类,这样他们就可以访问各自的函数并获取其特定的属性,如BaseDamage(如果它是武器) .

我试过使用一个名为类型类的ItemClass的XmlElement,但是我得到一个错误,说XmlElement / XmlAttribute在这个声明类型上无效...

我还考虑过使用抽象的Item类,但是如何将项ID加载到抽象基类Item,然后将BaseDamage加载到派生类Weapon?

这是我用来(反序列化?我不确定这是正确的术语)XML文件的代码:

[XmlRoot("ItemCollection")]
public class ItemContainer
{
    [XmlArray("Items")]
    [XmlArrayItem("Item")]
    public List<Item> items = new List<Item>();

    public static ItemContainer Load(string itemPath)
    {
        TextAsset _xml = Resources.Load<TextAsset>(itemPath);

        XmlSerializer serializer = new XmlSerializer(typeof(ItemContainer));

        StringReader reader = new StringReader(_xml.text);

        ItemContainer items = serializer.Deserialize(reader) as ItemContainer;

        reader.Close();

        return items;
    }
}

所以,欢迎任何帮助,

谢谢

2 回答

  • 0

    试试这个代码示例,xml和c#的好工具是xml2csharp

    class Program
    {
        static void Main(string[] args)
        {
            var xml = File.ReadAllText("test.xml");
            var serializer = new XmlSerializer(typeof(ItemCollection));
            using (var reader = new StringReader(xml))
            {
                var items = serializer.Deserialize(reader) as ItemCollection;
            }          
        }
    }
    
    [XmlRoot(ElementName = "Item")]
    public class Item
    {
        [XmlElement(ElementName = "Name")]
        public string Name { get; set; }
        [XmlElement(ElementName = "Damage")]
        public string Damage { get; set; }
        [XmlAttribute(AttributeName = "ID")]
        public string ID { get; set; }
        [XmlElement(ElementName = "Armor")]
        public string Armor { get; set; }
    }
    
    [XmlRoot(ElementName = "Items")]
    public class Items
    {
        [XmlElement(ElementName = "Item")]
        public List<Item> Item { get; set; }
    }
    
    [XmlRoot(ElementName = "ItemCollection")]
    public class ItemCollection
    {
        [XmlElement(ElementName = "Items")]
        public Items Items { get; set; }
    }
    
  • 0

    虽然第一个答案并不完全是我想要的,但它确实让我走上了正确的轨道,因为我使用了多个根并通过谷歌搜索,我落在某个网站上并意识到解决方案只是告诉我我不打算使用Item类的XML文件,而是Weapon / Armor / Scroll等,以便它们可以被视为各自的派生类 .

    它是这样的:

    [XmlRoot("ItemCollection")]
    public class ItemContainer
    {
        [XmlArray("Items")]
        [XmlArrayItem("Weapon", Type = typeof(Weapon))]
        [XmlArrayItem("Armor", Type = typeof(Armor))]
        public List<Item> items = new List<Item>();
    
        public static ItemContainer LoadItems(string itemPath)
        {
            TextAsset _xml = Resources.Load<TextAsset>(itemPath);
    
            XmlSerializer serializer = new XmlSerializer(typeof(ItemContainer));
    
            StringReader reader = new StringReader(_xml.text);
    
            ItemContainer items = serializer.Deserialize(reader) as ItemContainer;
    
            reader.Close();
    
            return items;
        }
    }
    

    我没有看过protoBuff,我发现的唯一的东西就是协议缓冲区,这似乎就是你所说的 . 我会记住它,但是现在对于我对C#的基本理解可能有点太多了

    <?xml version="1.0" encoding="utf-8" ?>
    
    <ItemCollection>
      <Items>
    
        <Weapon Name ="Dagger">
          <ID>01</ID>
          <BaseDamage>10</BaseDamage>
        </Weapon>
    
        <Armor Name ="Chainmail">
          <ID>04</ID>
          <BaseArmor>5</BaseArmor>
        </Armor>
    
      </Items>
    </ItemCollection>
    

相关问题