tags:

views:

75

answers:

2

I have an XML document that looks like this

    <Elements>
     <Element>
      <DisplayName />
      <Type />
     </Element>
    </Elements>

I have an interface,

interface IElement
{
    string DisplayName {get;}
}

and a couple of derived classes:

public class AElement: IElement

public class BElement: IElement

What I want to do is write the most efficient query to iterate through the XML and create a list of IElement, containing AElement or BElement, based on the 'Type' property in the XML.

So far I have this:

IEnumerable<AElement> elements = 
    from xmlElement in XElement.Load(path).Elements("Element")
    where xmlElement.Element("type").Value == "AElement"
    select new AElement(xmlElement.Element("DisplayName").Value);

return elements.Cast<IElement>().ToList();

But this is only for AElement. Is there a way to add BElement in the same query, and also make it generic IEnumerable<IElement>? Or would I have to run this query once for each derived type?

+5  A: 

You could use the conditional operator:

IEnumerable<IElement> elements = 
    from xmlElement in XElement.Load(path).Elements("Element")
    let type = (string)xmlElement.Element("Type")
    let name = (string)xmlElement.Element("DisplayName")
    select type == "AElement"
         ? (IElement)new AElement(name)
         : (IElement)new BElement(name);

Or, using regular syntax:

IEnumerable<IElement> elements =
    XElement.Load(path)
            .Elements("Element")
            .Select(xmlElement =>
{
    var type = (string)xmlElement.Element("Type");
    var name = (string)xmlElement.Element("DisplayName");

    switch (type)
    {
        case "AElement": return (IElement)new AElement(name);
        case "BElement": return (IElement)new BElement(name);
    }

    throw new Exception();
});
dtb
That would get nasty if he has more than 2 sub-types.
Aren
@Aren B: Indeed. I've added an alternative solution.
dtb
Thank you very much for your help. How can I write switch statement in linq syntax? I gave an example of only AElement and BElement, but in reality there are more. Is the only way to do so is using regular syntax?
Rita
@Rita: `switch` is a statement, not an expression, so you can't use it in LINQ syntax.
dtb
@dtb: Thank you very much!
Rita
A: 
IEnumerable<IElement> elements = 
    from e in XElement.Load(path).Elements("Element")
    let elType = e.Element("Type").Value
    let elName = e.Element("Name").Value
    where elType == "AElement" || elType == "BElement" 
    select 
        elType == "AElement" 
            ? (IElement) new AElement( name )
            : (IElement) new BElement( name );
Fyodor Soikin