Как я могу перебрать коллекцию объектов, возвращаемых запросом LINQ-to-XML? - PullRequest
1 голос
/ 16 мая 2010

У меня есть этот XML:

<BillingLog>
  <BillingItem>
    <date-and-time>2003-11-04</date-and-time>
    <application-name>Billing Service</application-name>
    <severity>Warning</severity>
    <process-id>123</process-id>
    <description>Timed out on a connection</description>
    <detail>Timed out after three retries.</detail>
  </BillingItem>
  <BillingItem>
    <date-and-time>2010-05-15</date-and-time>
    <application-name>Callback Service</application-name>
    <severity>Error</severity>
    <process-id>456</process-id>
    <description>Unable to process callback</description>
    <detail>Reconciliation timed out after two retries.</detail>
  </BillingItem>
</BillingLog>

То, что я хочу с помощью LINQ-to-XML проецировать в коллекцию объектов BillingItem, содержащихся в одном объекте BillingLog.

public class BillingLog
{
    public IEnumerable<BillingItem> items { get; set; }
}

public class BillingItem
{
    public string Date { get; set; }
    public string ApplicationName { get; set; }
    public string Severity { get; set; }
    public int ProcessId { get; set; }
    public string Description { get; set; }
    public string Detail { get; set;}       
}

Это запрос LINQ, который я использую для проецирования XML (который содержится в строковой переменной source ).

XDocument xdoc = XDocument.Parse(source);

var log = 
    from i in xdoc.Elements("BillingLog")
    select new BillingLog
    {
        items =
            from j in i.Descendants("BillingItem")
            select new BillingItem
            {
                Date = (string)j.Element("date-and-time"),
                ApplicationName = (string)j.Element("application-name"),
                Severity = (string)j.Element("severity"),
                ProcessId = (int)j.Element("process-id"),
                Description = (string)j.Element("description"),
                Detail = (string)j.Element("detail")
            }
    };

Когда я пытаюсь перебрать объекты в log , используя foreach.

foreach (BillingItem item in log)
{
Console.WriteLine ("{0} | {1} | {2} | {3} | {4} | {5}", 
                    item.Date, item.ApplicationName, 
                    item.Severity, item.ProcessId.ToString(), 
                    item.Description, item.Detail);
}   

Я получаю следующее сообщение об ошибке от LINQPad.

Cannot convert type 'UserQuery.BillingLog' to 'UserQuery.BillingItem'

Заранее спасибо.

1 Ответ

3 голосов
/ 16 мая 2010

Это потому, что ваша переменная log содержит коллекцию BillingLog объектов, а не BillingItem. Вы должны сделать что-то вроде:

foreach( BillingLog l in log )
{
    foreach( BillingItem item in l.items )
    {
        Console.WriteLine( ... );
    }
}

В качестве альтернативы, если ваше первоначальное намерение состояло в том, чтобы просто выбрать все BillingItem с, полностью игнорируя их родительские BillingLog с, вы можете переписать свой запрос следующим образом:

var log = 
        from l in xdoc.Elements("BillingLog")
        from j in l.Descendants("BillingItem")
        select new BillingItem
        {
            Date = (string)j.Element("date-and-time"),
            ApplicationName = (string)j.Element("application-name"),
            Severity = (string)j.Element("severity"),
            ProcessId = (int)j.Element("process-id"),
            Description = (string)j.Element("description"),
            Detail = (string)j.Element("detail")
        }

Это даст вам простую коллекцию всех BillingItems, выбранных из-под всех BillingLog с, а сами BillingLog будут полностью отброшены.

...