LINQ:将XML加载到字典中,其值等于新的自定义类实例

本文关键字:于新 自定义 实例 XML 加载 字典 LINQ | 更新日期: 2023-09-27 18:21:20

这里有两个LINQ语句。基本上,我想将以下两个XML文件转换为字典(键入详细信息)。以下是XML的快照:

偏移XML:

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

所需输出:Dictionary<string, IntPtr>。我有一个名为GetPointerFromBaseOffsets(int[]offset)的方法,它从带有偏移量的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<string, 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")));

问题:在尝试创建偏移字典时,我收到了第一条错误消息(运行时),即它不能进行Cast。有人能教我怎么写这两个方块吗?

谢谢!

LINQ:将XML加载到字典中,其值等于新的自定义类实例

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呼叫。