【问题标题】:XML to Dictionary to Instances of Custom ClassXML 到字典到自定义类的实例
【发布时间】:2014-11-13 02:22:41
【问题描述】:

我想知道是否有比我在下面展示的更直接/优雅的方式从 XML 文件中获取数据并从中创建自定义类的实例。以下是我目前的做法(有效,但可能有点笨拙)。

我的 XML:

<Skills>
  <Fire>
    <Cast>0.00</Cast>
    <ReCast>90.00</ReCast>
    <MPCost>0</MPCost>
    <Button>8</Button>
  </Fire>
  <Ice>
    <Cast>5.98</Cast>
    <ReCast>2.49</ReCast>
    <MPCost>0</MPCost>
    <Button>9</Button>
  </Ice>
</Skills>

1) 将 XML 中的元素加载到字典中:

//Load Skill list
var skillXElement = XDocument.Load(path + @"\Skills.xml").Root;
if (skillXElement != null)
    SkillDictionary =
        skillXElement.Elements()
            .ToDictionary(e => e.Name.LocalName,
                e =>
                    new Skill(e.Name.LocalName, (double) e.Element("Cast"), (double) e.Element("ReCast"),
                        (int) e.Element("MPCost"), e.Element("Button").Value[0]));

2) 根据字典创建对技能类的引用:

class SkillInfo
{
    public Skill Fire { get; private set; }
    public Skill Ice { get; private set; }

    public SkillInfo()
    {
        Fire = Globals.Instance.SkillDictionary["Fire"];
        Ice= Globals.Instance.SkillDictionary["Ice"];
    }
}

3) 最后,我通过公共财产访问技能:

class Player : Character
{
    public Player()
    {
        SkillInfo = new SkillInfo();
    }

    public SkillInfo SkillInfo { get; private set; }

    private ExampleMethod()
    {
        UseSkill(SkillInfo.Fire);
    }
}

您可能想知道为什么我不直接从字典中访问每个技能:UseSkill(Globals.Instance.SkillDictionary["Fire"]);。原因是字典中的每次查找都相当慢(大约 500 毫秒),尽管是 O(1)。因此,为了避免每次使用技能时出现延迟,我创建了 SkillInfo 类。

任何关于如何更优雅地从 XML 到类实例的提示或想法都将受到高度赞赏。

提前致谢!

编辑:要求提供以下附加信息

  • 我的设置器是私有的以确保封装。这是我觉得可以使用的最严格的访问修饰符。除此之外没有其他要求

【问题讨论】:

  • 您的 Fire 和 Ice 属性是否需要私有 setter 或可以公开?..还有 Character 类中的 SkillInfo 属性?
  • @terrybozzio 提前感谢您的帮助!属性中的所有设置器都是私有的,因为我想确保封装。它基本上是我可以使用的“最严格”的访问修饰符。这不是一个要求。我会将此信息添加到问题中

标签: c# xml performance dictionary


【解决方案1】:

只需将MemoryStream 替换为StreamReader 即可从文件中读取:

void Main()
{
    var xml = @"<Skills>
                    <Fire>
                        <Cast>0.00</Cast>
                        <ReCast>90.00</ReCast>
                        <MPCost>0</MPCost>
                        <Button>8</Button>
                    </Fire>
                    <Ice>
                        <Cast>5.98</Cast>
                        <ReCast>2.49</ReCast>
                        <MPCost>0</MPCost>
                        <Button>9</Button>
                    </Ice>
                </Skills>";

    using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
    {
        var serializer = new XmlSerializer(typeof(Skills));
        var skills = (Skills)serializer.Deserialize(memoryStream);
        // good to go!
    }
}

public class Skill
{
    public double Cast { get; set; }
    public double ReCast { get; set; }
    public int MPCost { get; set; }
    public int Button { get; set; }
}

public class Skills
{
    public Skill Fire { get; set; }
    public Skill Ice { get; set; }
}

【讨论】:

  • 没错,也许我对“从 XML 文件中获取数据并从中创建自定义类的实例”过于重视。
  • 权重不​​要太大:) OP 需要澄清它是否必须使用以及为什么使用私有 setter。
  • 不,这是“技能”的单个实例。 'Fire' 和 'Ice' 由 XmlSerializer 在反序列化时设置,因为 XML 元素与类中的属性名称匹配。编辑:我在示例 xml/code 中将 SkillInfo 重命名为 Skills。
  • 没有属性上的属性,是的。但是你可以把 [XmlElement("the name of the xml element")] 放在一个属性的上面,如果你想让属性名不是 XML 元素名的话。
  • 1) 它们由序列化程序设置。 2)您可能有其他构造函数,但您必须有一个无参数的构造函数。 3) 无参数的将被序列化程序调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2014-02-15
  • 2017-02-05
  • 2015-04-23
  • 1970-01-01
相关资源
最近更新 更多