LINQ to XML - Как получить словарь от анонимного объекта? - PullRequest
2 голосов
/ 29 апреля 2010

В настоящее время я получаю список HeaderColumns из следующего фрагмента XML:

<PerformancePanel>
  <HeaderColumns>
    <column performanceId="12" text="Over last month %" />
    <column performanceId="13" text="Over last 3 months %" />
    <column performanceId="16" text="1 Year %" />
    <column performanceId="18" text="3 Years % p.a." />
    <column performanceId="20" text="5 Years % p.a." />
    <column performanceId="22" text="10 Years % p.a." />
  </HeaderColumns>
</PerformancePanel>

из которого я создаю объект следующим образом: (восхитительно похож на предыдущий вопрос!)

var performancePanels = new
{
    Panels = (from panel in doc.Elements("PerformancePanel")
            select new
            {
                HeaderColumns = (from column in panel.Elements("HeaderColumns").Elements("column")
                                 select new
                                 {
                                     PerformanceId = (int)column.Attribute("performanceId"),
                                     Text = (string)column.Attribute("text")
                                 }).ToList(),
              }).ToList()
};

Я бы хотел, чтобы HeaderColumns был Dictionary (), поэтому позже я извлекаю значения из анонимного объекта следующим образом:

Dictionary<int, string> myHeaders = new Dictionary<int, string>();
foreach (var column in performancePanels.Panels[0].HeaderColumns)
{
    myHeaders.Add(column.PerformanceId, column.Text);
}

Я думал, что смогу добиться этого с помощью Linq to XML с чем-то похожим на это

HeaderColumns = (from column in panel.Elements("HeaderColumns").Elements("column")
                 select new Dictionary<int, string>()
                 {
                     (int)column.Attribute("performanceId"),
                     (string)column.Attribute("text")
                 }).ToDictionary<int,string>(),

но это не работает, потому что

  1. ToDictionary () нужен параметр Func, и я не знаю, что это такое / как это реализовать, и
  2. код, вероятно, неверен в любом случае!

Может кто-нибудь подсказать, как мне добиться нужного мне результата? Благодарю.

Редактировать: Я пытался реализовать решение решения Спендера ниже, но мне трудно понять, что мне нужно изменить в моем коде. Может кто-нибудь уточнить? Спасибо

Ответы [ 3 ]

2 голосов
/ 29 апреля 2010

Это не проверено, но следует сделать трюк:

panel
    .Elements("HeaderColumns")
    .Elements("column")
    .ToDictionary(
        column=>(int)column.Attribute("performanceId"),
        column=>(string)column.Attribute("text")
    )

В этом случае я использую следующую перегрузку ToDictionary :

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, TElement> elementSelector
)

Итак, здесь source будет:

panel
    .Elements("HeaderColumns")
    .Elements("column")

И keySelector и elementSelector являются функциями (делегатами), которые принимают элемент типа TSource (из source) и возвращают значение, полученное из элемента:

keySelector

        column=>(int)column.Attribute("performanceId")

elementSelector:

        column=>(string)column.Attribute("text")

Они объявлены в лямбда-формате. Тип словаря затем определяется по типам возврата этих делегатов. В данном случае это будет Dictionary<int,string>.

Общий делегат Func<TSource, TKey> будет определять тип метода, который принимает параметр типа TSource и возвращает значение типа TKey. Очень важно понять, что именно означает продуктивное время, используя методы расширения Linq.

1 голос
/ 29 апреля 2010

Трудно дать полный ответ, так как ваши xml и C # не совпадают; но из каждого "HeaderColumns" вы можете использовать:

var columns = from column in headerColumns.Elements("column")
              select new {
                  PerformanceId = (int)column.Attribute("performanceId"),
                  Text = (string)column.Attribute("text")
              };
Dictionary<int, string> myHeaders = columns.ToDictionary(
    column => column.PerformanceId, column => column.Text);

Если у вас есть несколько <HeaderColumns>, то SelectMany возможно ...

var columns = from panel in doc.Elements("PerformancePanel")
              from headers in panel.Elements("HeaderColumns")
              from column in headers.Elements("column")
              select new {
                  PerformanceId = (int)column.Attribute("performanceId"),
                  Text = (string)column.Attribute("text")
              };
Dictionary<int, string> myHeaders = columns.ToDictionary(
    column => column.PerformanceId, column => column.Text);
0 голосов
/ 14 мая 2010

Я нашел это подходящим ответом на этот вопрос:

Как создать словарь через LINQ to XML?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...