LINQ to XML - 如何从匿名对象获取字典?

时间:2010-04-28 22:42:26

标签: c# linq dictionary

目前,我从以下XML代码段中获取了一个HeaderColumns列表:

<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. 有人可以建议我如何才能达到我需要的结果吗?谢谢。

    编辑:我尝试在下面实施Spender的解决方案解决方案,但我很难理解我需要在代码中更改的内容。有人可以澄清一下吗?感谢

3 个答案:

答案 0 :(得分:2)

这是未经测试的,但应该这样做:

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

在这种情况下,我使用以下overload of 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")

keySelectorelementSelector是带有TSource类型元素(来自source)的函数(委托),并返回从元素派生的值:

keySelector

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

elementSelector

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

这些是以lambda格式声明的。然后从这些委托的返回类型推断出字典的类型。在这种情况下,这将是Dictionary<int,string>

泛型委托Func<TSource, TKey>将定义采用TSource类型的参数并返回TKey类型值的方法的类型。准确掌握使用Linq扩展方法获得生产时间的意义非常重要。

答案 1 :(得分:1)

由于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);

答案 2 :(得分:0)

我发现这是对这个问题的合适答案:

How to Create Dictionary<int, string> via LINQ to XML?