tags:

views:

54

answers:

2

I'm trying to take one attribute to use as the key, and another to use as the value. If I use (xDoc is an XDocument object in the example):

Dictionary<string, XElement> test = xDoc.Descendants()
    .Where<XElement>(t => t.Name == "someelement")
    .ToDictionary<XElement, string>(t => t.Attribute("myattr").Value.ToString());

I get a dictionary with the myattr value as key (which is what I want) but the entire XElement object as the value.

What I want to do, is to select a second attribute to set as the value property on each dictionary item, but can't seem to figure that out.

Is it possible to do all of this in 1 Linq statement? Curiousity has caught me!

Cheers!

+2  A: 

Yes, you can pass in another expression to select the value you want:

Dictionary<string,string> test = xDoc.Descendants()
    .Where(t => t.Name == "someelement")
    .ToDictionary(
        t => t.Attribute("myattr").Value.ToString(), 
        t => t.Attribute("otherAttribute").Value.ToString());
driis
Works great! Thanks for the answer, but why does the casting change things? If I have casting in the second expression it looks for is a comparer.
AndyC
@AndyC, what are you trying to cast ? .ToDictionary has some different overloads, one of them taking a comparer.
driis
@driis in my original code I had <XElement, string>, taking this out has made it work. Just curious as to why that is.
AndyC
@AndyC, then it was because you are explicitly stating the types for the dictionary to be <XElement, string>, so the extension method expects the value to be XElement. When it sees another type, it tries the other overloads, and then complains because it doesn't match. In general, you should not explicitly state the types on the extension methods using LINQ. Doing so only adds visual noise.
driis
+1  A: 

The casting in your .ToDictionary() call flips the parameters around from your object definition.

All you have to do is drop it and add an identity select and it should work.

Dictionary<string, XElement> test = xDoc.Descendants()
            .Where<XElement>(t => t.Name == "someelement")
            .ToDictionary(t => t.Attribute("myattr").Value.ToString(), t => t);
48klocs