简体   繁体   English

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

[英]Using an XML to (parse?) elements in multiple different classes C#

I'm truly sorry if the answer exist here under another name but I've been trying to figure this out for a week or so and haven't found anything similar. 如果答案以其他名字存在,我真的很抱歉,但是我一直试图找出一个星期左右,并且没有发现任何类似的东西。

So, I'm building an Item system for a game in unity. 因此,我正在为一个游戏构建一个物品系统。 There is an Item class with these properties 有一个具有这些属性的Item类

public int ItemId;
public string ItemName;

For simplicity, let's say I want to have two derived classes, Weapon and Armor, with a BaseDamage property for Weapon and BaseArmor for Armor. 为简单起见,假设我要有两个派生类,即Weapon和Armor,其中Weapon具有BaseDamage属性,而Armor具有BaseArmor。

I also want to load the items in an ItemContainer class from XML and ideally, from the same XML file rather than one for the weapons, one for armors and one for, say, potions. 我还想从XML加载项目到ItemContainer类中,理想情况下,是从同一个XML文件而不是用于武器,用于装甲和用于药水的项目。

I've tried multiple ways but so far the only way I've been able to succeed is by adding the BaseDamage and BaseArmor to the Item base class... like this : 我已经尝试了多种方法,但是到目前为止,我唯一能够成功的方法是将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;
}

and simply not adding the element to the XML file for some items : 并且只是不将某些项目的元素添加到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>

It does work, but I feel like this isn't the correct way to do it. 它确实有效,但是我觉得这不是正确的方法。 Another issue is that if I want to add a Scroll class with a certain function to cast the spell written on that scroll, I need to add the "SpellToCast" property to the base class AND add a CastSpell(Spell) function to it that could be called from any item, which is not what I want... 另一个问题是,如果我想添加一个具有某个函数的Scroll类以转换在该滚动条上写入的咒语,则需要向基类添加“ SpellToCast”属性,并向其添加CastSpell(Spell)函数可以从任何项目中调用,这不是我想要的...

In short, I'd want to load multiple items from the XML but with each being of their intended derived class so that they get access to their respective functions and get their specific properties such as BaseDamage if it's a weapon. 简而言之,我想从XML加载多个项目,但每个项目都是其预期的派生类,以便它们能够访问各自的功能并获得其特定属性,例如BaseDamage(如果有的话)。

I've tried to use an XmlElement called ItemClass of type class, but I get an error saying that XmlElement/XmlAttribute is not valid on this declaration type... 我尝试使用类型类别为ItemClass的XmlElement,但出现一条错误消息称XmlElement / XmlAttribute在此声明类型上无效...

I also thought about using an abstract Item class instead but then how do I load the item ID to the abstract base class Item and then BaseDamage to the derived class, Weapon? 我还考虑过使用抽象的Item类,但是如何将Item ID加载到抽象基类Item,然后将BaseDamage加载到派生类Weapon?

This is the code I use to (deserialize? I'm not sure that's the correct term) the XML file : 这是我用来(反序列化?我不确定这是正确的术语)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;
    }
}

So, any help is welcome, 因此,欢迎任何帮助,

Thanks 谢谢

Try this code example, a good tool for xml and c# is xml2csharp 试试这个代码示例,一个适合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; }
}

While the first answer wasn't exactly what I was looking for, it did send me on the correct track as I looked into using multiple roots and by googling for that, I fell on a certain website and realized that the solution was simply to tell the XML file that I'm not going to use the Item Class but rather Weapon / Armor / Scroll and such so that they can be considered as their respective derived class. 虽然第一个答案并非我真正想要的答案,但是当我尝试使用多个词根时,它的确使我走上了正确的轨道,并且通过谷歌搜索,我进入了某个网站,意识到解决方案只是在告诉我XML文件,我将不使用Item类,而是使用Weapon / Armor / Scroll等,以便可以将它们视为各自的派生类。

Did it like this : 这样吗:

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

I haven't looked at protoBuff, the only thing I found was protocol buffer, which seems to be what you were talking about. 我没有看过protoBuff,我发现的唯一东西就是协议缓冲区,这似乎就是您在谈论的内容。 I'll keep it in mind but right now it might be a bit too much for my basic understanding of C# in general 我会牢记这一点,但就我目前对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>

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

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