LINQ: загрузка XML в словарь со значением, равным новым экземплярам пользовательских классов
Немного борюсь с двумя утверждениями LINQ здесь. В основном я хотел бы преобразовать следующие два XML-файла в словари (тип-детали, чтобы следовать). Вот снимки XML:
Смещение XML:
<Offsets>
<PlayerStructBase>0xF24C10</PlayerStructBase>
<HP>
<offset>0x17e8</offset>
</HP>
<MaxHP>
<offset>0x17ec</offset>
</MaxHP>
</Offsets>
Желаемый результат: Dictionary<string, IntPtr>
, У меня есть метод с именем GetPointerFromBaseOffsets (смещение int[]), который возвращает IntPtr из массива int со смещением (пример: 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>
, 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")));
Вопрос: При попытке создать словарь смещения я получаю свое первое сообщение об ошибке (во время выполнения), что оно не может быть преобразовано. Может ли кто-нибудь показать мне, как написать эти два блока?
Спасибо!
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
вызов.