【问题标题】:LINQ: Load XML into a Dictionary with value equaling new custom class instancesLINQ:将 XML 加载到字典中,其值等于新的自定义类实例
【发布时间】:2014-09-09 22:32:35
【问题描述】:

在这里使用两个 LINQ 语句有点吃力。基本上我想将以下两个 XML 文件转换为字典(后面的类型详细信息)。以下是 XML 的快照:

偏移 XML:

<Offsets>
  <PlayerStructBase>0xF24C10</PlayerStructBase>
  <HP>
    <offset>0x17e8</offset>
  </HP>
  <MaxHP>
    <offset>0x17ec</offset>
  </MaxHP>
</Offsets>

所需输出:Dictionary&lt;string, IntPtr&gt;。我有一个名为 GetPointerFromBaseOffsets(int[] offsets) 的方法,它从带有偏移量的 int 数组返回 IntPtr(例如:0x1234, 0x17e2)。

技能 XML:

<Skills>
  <Potion>
    <Cast>0.00</Cast>
    <ReCast>60.00</ReCast>
    <MPCost>0</MPCost>
  </Potion>
  <Ruin>
    <Cast>2.49</Cast>
    <ReCast>2.49</ReCast>
    <MPCost>9</MPCost>
  </Ruin>
</Skills>

所需输出:Dictionary&lt;string, Skill&gt;。 Skill 是一个具有 Cast、ReCast 和 MpCost 等属性的类。


这些是我的尝试:

将 XML 偏移到字典

OffsetDictionary =
    XDocument.Load(folderPath+@"\offsets.xml")
        .XPathSelectElements("/Offsets/*[offset]")
        .ToDictionary(o => o.Name.LocalName,
            o => MemoryManager.GetPointerFromBaseOffsets(Enumerable.Cast<int>(o.Elements()).ToArray()));

技能 XML 到字典

SkillDictionary =
    XDocument.Load(folderPath + @"\skills.xml")
        .XPathSelectElements("/Skills/*")
        .ToDictionary(e => e.Name.LocalName, e => new Skill(e.Name.LocalName, (double)e.Element("Cast"), (double)e.Element("ReCast"), (int)e.Element("MPCost")));

问题:在尝试创建 Offset 字典时,我收到第一条错误消息(运行时),它不能进行 Cast。谁能告诉我如何写这两个块?

谢谢!

【问题讨论】:

    标签: c# xml linq dictionary


    【解决方案1】:

    Enumerable.Cast 不执行自定义 转换,这是您想要的。您需要直接投射 - 但这很简单:

    OffsetDictionary =
        XDocument.Load(folderPath+@"\offsets.xml")
            .XPathSelectElements("/Offsets/*[offset]")
            .ToDictionary(o => o.Name.LocalName,
                o => MemoryManager.GetPointerFromBaseOffsets(o.Elements()
                                                              .Select(x => (int) x)
                                                              .ToArray()));
    

    但是,这假设您的偏移量实际上只是普通的十进制整数。在您的情况下,它们不是-它们是十六进制的。你需要做更多的工作来解析这些,例如

    .Select(x => int.Parse(x.Value.Substring(2), NumberStyles.AllowHexSpecifier))
    

    或者,更改您的 XML 格式,使值以十进制表示。

    虽然我不确定您的 XPath 表达式...无论如何我都不是 XPath 专家,但是您不希望所有元素都位于根元素的正下方吗?如果是这样,您可以使用

    .Root.Elements()
    

    而不是您的XPathSelectElements 电话。

    【讨论】:

    • 再次感谢乔恩。我收到此错误消息:“在 mscorlib.dll 中发生了 'System.FormatException' 类型的未处理异常”。 “附加信息:输入字符串的格式不正确。”我觉得我错过了一些简单的东西。提前感谢您的指导..
    • @Magnus:那个错误的堆栈跟踪是什么?在不知道发生了什么故障的情况下,很难提供更多帮助。但我不确定您的o.Elements() 电话是否正确——您确定您的XPath 吗?我将编辑我的答案...
    • @Magnus:啊,我现在明白了——事实上你的偏移量是十六进制的。再次编辑。
    • 很好,谢谢,现在试试。 'XPathSelectElements' 背后的想法是,例如,在 HP 下,可能有多个元素,都具有相同的标记 ()。现在测试一下
    • @Magnus:但是你想用它做什么?当然你想要的元素是HP,而不是offset...你以后已经得到了所有的子元素。
    猜你喜欢
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多