2010-06-01 42 views
1

我有一個看起來像這樣的LINQ to XML,檢索通用的基於接口的列表

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

我有一個接口的XML文檔,

interface IElement 
{ 
    string DisplayName {get;} 
} 

和幾個派生類:

public class AElement: IElement 

public class BElement: IElement 

我想要做的是編寫最有效的查詢來遍歷XML並創建一個列表IElement,包含AElementBElement,基於XML中的'Type'屬性。

到目前爲止,我有這樣的:

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(); 

但這僅僅是爲AElement。有沒有辦法在相同的查詢中添加BElement,並使其通用IEnumerable<IElement>?或者我將不得不爲每個派生類型運行一次這個查詢?

回答

6

您可以使用條件運算符:

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

或者,使用常規語法:

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(); 
}); 
+0

這將變得骯髒,如果他有2個以上的子類型。 – Aren 2010-06-01 18:03:11

+0

@Aren B:的確如此。我添加了一個替代解決方案。 – dtb 2010-06-01 18:05:29

+0

非常感謝您的幫助。我怎樣才能用linq語法編寫switch語句?我舉了一個AElement和BElement的例子,但實際上還有更多。唯一的方法是使用常規語法? – Rita 2010-06-01 19:15:44

0
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);