NullReferenceException для этого кода C # - PullRequest
0 голосов
/ 26 октября 2010

Вот полный код моего класса:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml.Linq;

namespace SharpDIC.Entities
{
    /// <summary>
    /// Represents a forum on the Dream.In.Code website.
    /// </summary>
    public class Forum
    {
        //Forum information is given by this XML call:
        //http://www.dreamincode.net/forums/xml.php?showforum=NUMBER_GOES_HERE

        public string Name { get; set; }
        public string ID { get; set; }
        public string URL { get; set; }
        public List<Subforum> Subforums { get; set; }

        /// <summary>
        /// Load a forum by providing an ID.
        /// </summary>
        /// <param name="id">A forum's individual ID number.</param>
        public Forum(string ID)
        {
            WebClient webClient = new WebClient();
            string htmlSource = webClient.DownloadString(new Uri(String.Format("http://www.dreamincode.net/forums/xml.php?showforum={0}", ID)));
            XDocument xml = XDocument.Parse(htmlSource);

            var forumXML = xml.Element("ipb").Element("forum");

            //Load general profile information.
            this.Name = forumXML.Element("name").Value;
            this.ID = forumXML.Element("id").Value;
            this.URL= forumXML.Element("url").Value;

            //Load subforums.
            var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");
            this.Subforums = (from forum in subforumsXML.Descendants("forum")
                              select new Subforum()
                              {
                                  ID = forum.Element("id").Value,
                                  Name = forum.Element("name").Value,
                                  URL = forum.Element("url").Value,
                                  Description = forum.Element("description").Value,
                                  Type = forum.Element("type").Value,
                                  TopicCount = forum.Element("topics").Value,
                                  ReplyCount = forum.Element("replies").Value,
                                  LastPost = new LastPost()
                                  {
                                      Date = forum.Element("lastpost").Element("date").Value,
                                      Name = forum.Element("lastpost").Element("name").Value,
                                      ID = forum.Element("lastpost").Element("id").Value,
                                      URL = forum.Element("lastpost").Element("url").Value,
                                      UserWhoPosted = new Friend()
                                      {
                                          ID = forum.Element("lastpost").Element("user").Element("id").Value,
                                          Name = forum.Element("lastpost").Element("user").Element("name").Value,
                                          Url = forum.Element("lastpost").Element("user").Element("url").Value,
                                          Photo = forum.Element("lastpost").Element("user").Element("photo").Value,
                                      }
                                  }
                              }).ToList();
        }
    }
}

По сути, он анализирует информацию из возвращенного XML-адреса этого адреса:

http://www.dreamincode.net/forums/xml.php?showforum=1

Вот как я запускаю этот код:

SharpDIC.Entities.Forum forum = new SharpDIC.Entities.Forum("1");
Console.WriteLine(forum.Name);
Console.WriteLine(forum.URL);
Console.WriteLine(forum.ID);
Console.WriteLine(forum.Subforums[0].LastPost.UserWhoPosted.Name);

Console.ReadLine();

Я получаю исключение для всего блока загрузки подфорумов;какие-либо предложения?

NullReferenceException was not handled. Object reference not set to an instance of an object.

Ответы [ 5 ]

1 голос
/ 26 октября 2010

Почти наверняка отсутствует один из ожидаемых вами элементов.

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

В качестве альтернативы разбейте анализ отдельных компонентов на отдельные методы:

this.Subforums = subforumsXML.Descendants("forum")
                             .Select(ParseForum)
                             .ToList();

...

static SubForum ParseForum(XElement forum)
{
    return new Subforum
    {
        ID = forum.Element("id").Value,
        ...
        LastPost = ParseLastPost(forum.Element("lastpost"))
    };
}

static LastPost ParseLastPost(XElement lastPost)
{
    ...
}

Я обнаружил, что это может сделать выражения запросов более управляемыми.

Один из способов избежать NRE, когда есть пропущенный элемент, значение которого вы просто пытаетесь получить, - это использовать преобразование вместо свойства Value, например,

ID = (string) forum.Element("id")

Это установит ID на null, если элемент id отсутствует. Очевидно, что если на самом деле это обязательное свойство , генерировать исключение лучше, но для дополнительных свойств это действительно полезно.

0 голосов
/ 26 октября 2010

Чтобы найти проблему, попробуйте это расширение и затем вызовите GetElement вместо Element ...

public static System.Xml.Linq.XElement GetElement(this System.Xml.Linq.XContainer doc, string name)
    {
        var element = doc.Element(name);
        if (element == null)
            throw new ApplicationException("Missing element: " + name);
        return element;
    }
0 голосов
/ 26 октября 2010

В вашей ссылке у первых пользователей нет фото, это может быть

0 голосов
/ 26 октября 2010

Вы никогда не проверяете, существует ли элемент. Например, для UserWhoPosted каждый элемент должен иметь элемент <lastpost>, который должен иметь элемент <user>, который должен иметь <id>, <name>, <url> и <photo> элементов. Если какой-либо из них отсутствует, этот Элемент («что угодно») вернет ноль, поэтому .Value не удастся.

0 голосов
/ 26 октября 2010

Вам, вероятно, следует проверить, чтобы убедиться, что subforumsXML! = Null, прежде чем использовать на нем linq.

вы можете разбить эту операцию на пару строк ....

    var subforumsXML = xml.Element("ipb").Element("forum").Element("subforums");

// goes to

if ( forumXML != null )    // breakpoint here
{
   // ml.Element("ipb").Element("forum") == forumXML
   var subforumsXML = forumXML.Element("subforums");
   if ( subforumsXML != null )
   {
   // do stuff here
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...