Манипулирование существующим XDocument (не удается) - PullRequest
2 голосов
/ 18 мая 2010

Я получил следующий фрагмент кода из моего приложения Silverlight:

var messages = from message in XcurrentMsg.Descendants("message")
                               where    DateTime.Parse(message.Attribute("timestamp").Value).CompareTo(DateTime.Parse(MessageCache.Last_Cached())) > 0
                               select new
                               {
                                   ip = message.Attribute("ip").Value,
                                   timestamp = message.Attribute("timestamp").Value,
                                   text = message.Value,
                               };
                if (messages == null)
                    throw new SystemException("No new messages recorded. Application tried to access non existing resources!");

            foreach (var message in messages)
            {
                XElement temporaryElement = new XElement("message", message.text.ToString(), new XAttribute("ip", message.ip.ToString()), new XAttribute("timestamp", message.timestamp.ToString()));
                XcurrentMsg.Element("root").Element("messages").Add(temporaryElement);

                AddMessage(BuildMessage(message.ip, message.timestamp, message.text));
                msgCount++;
            }

            MessageCache.CacheXML(XcurrentMsg);
            MessageCache.Refresh();

XcurrentMsg - это XDocument, полученный с моего сервера и содержащий сообщения: Структура

<root>
    <messages>
          <message ip="" timestamp=""> Text </message>
    </messages>
</root>

Я хочу получить все "сообщения" новее, чем в прошлый раз, когда я кэшировал XcurrentMsg. Это прекрасно работает, пока я вырезаю "XElement временный элемент" и "XcurrentMsg.Element ...." и просто используйте строку currentMsg в качестве вывода. Но я хочу, чтобы «новые сообщения» сохранялись в моем XcurrentMsg / Cache. Теперь, если я не вырежу эту часть, моя заявка станет сумасшедшей. Я думаю, что он записывает бесконечные элементы в XcurrentMsg без остановки.

Не могу понять, в чем проблема.

С уважением,

Ответы [ 2 ]

1 голос
/ 18 мая 2010

Не уверен, что делает AddMessage, но вам следует отложить все добавления в XcurrentMsg до завершения foreach. Итак, возьми это:

foreach (var message in messages)
{
    XElement temporaryElement = new XElement("message", 
        message.text.ToString(), new XAttribute("ip", message.ip.ToString()), 
        new XAttribute("timestamp", message.timestamp.ToString()));
    XcurrentMsg.Element("root").Element("messages").Add(temporaryElement);

    AddMessage(BuildMessage(message.ip, message.timestamp, message.text));
    msgCount++;
}

И сделай так:

List<XElement> elementsToAdd = new List<XElement>();
foreach (var message in messages)
{
    XElement temporaryElement = new XElement("message", 
        message.text.ToString(), new XAttribute("ip", message.ip.ToString()), 
        new XAttribute("timestamp", message.timestamp.ToString()));
    elementsToAdd.Add(temporaryElement);

    AddMessage(BuildMessage(message.ip, message.timestamp, message.text));
    msgCount++;
}

XcurrentMsg.Element("root").Element("messages").Add(elementsToAdd.ToArray());

Надеюсь, это поможет!

1 голос
/ 18 мая 2010

Это классическая LINQ гоча.

Переменная messages содержит ссылку на IEnumerable<someAnonymousType>. Ошибка, которую вы совершаете, заключается в том, что после присвоения messages все Descendents были перечислены и набор someAnonymousType был построен.

На самом деле ничего не произошло на этом этапе. Только когда вы начинаете перечислять набор с помощью foreach, перечисляются Descendents и создаются анонимные типы. Даже в тот момент, когда весь набор Descendents не был перечислен, фактически только до первого элемента, который соответствует условию условия where, тогда одновременно создается только одна проекция (результат выбора), как foreach проходит через.

Следовательно, сообщения, которые вы добавляете, также включаются в перечисление, и потому что это вызывает другие сообщения, которые вы заканчиваете в бесконечном цикле, или, по крайней мере, ошибка с жалобой на вашу попытку изменить перечисляемую коллекцию.

Если вы хотите убедиться, что список перечисляемых элементов фиксирован, перед тем, как прекратить цикл, добавьте ToList() к запросу, это создаст List<T>.

var messages = (from message in XcurrentMsg.Descendants("message")
                           where    DateTime.Parse(message.Attribute("timestamp").Value).CompareTo(DateTime.Parse(MessageCache.Last_Cached())) > 0
                           select new
                           {
                               ip = message.Attribute("ip").Value,
                               timestamp = message.Attribute("timestamp").Value,
                               text = message.Value,
                           }).ToList();

Обратите внимание, что нет необходимости проверять messages на ноль в любом случае, это не будет ноль, это может быть пустое перечисление или список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...