вернуть класс напрямую из запроса linq - PullRequest
2 голосов
/ 25 мая 2011

Я все еще новичок в LINQ. Можно ли сделать следующее:

например, у меня есть класс:

public class Person
{
        public string FirstName { get; set; }
        public string LastName { get; set; }
}

Теперь я хочу вернуть его как объект класса, прочитав, скажем, содержимое XML-файла и вернув его.

Так что, если я прочитаю это XML-файл:

<person>
    <firstname></firstname>
    <lastname></lastname>
</person>

Читатель (скажем, это относится к классу людей):

public static Person ReadPerson(xmlpath)
{
    XDocument xd = XDocument.Load(xmlpath);
    var person = (from p in xd.Descendants("person")
                  select new Person
                  {
                      FirstName = p.Element("firstname").value,
                      LastName = p.Element("lastname").value
                  });
    return person as Person;
}

Теперь, если я сделаю следующее в другом месте:

Person p = new Person();
p = People.Person(xmlpath);
Response.Write(p.FirstName);

Здесь p.FirstName возвращает нулевое исключение. Что я понимаю, так это потому, что запрос linq возвратил пустой класс.

Итак, мой вопрос, есть ли способ напрямую добавить материал в класс в запросе и вернуть его БЕЗ запуска цикла foreach и добавления всего вручную ? (вроде следующего:)

Person p = new Person();
foreach (var x in person)
{
    p.FirstName = x.FirstName;
    p.LastName = x.LastName;
}

Извините, если это глупый вопрос.

Спасибо

Ответы [ 4 ]

4 голосов
/ 25 мая 2011

Необходимо различать чтение последовательности элементов и чтение одного элемента.В настоящее время переменная person в ReadPerson на самом деле имеет тип IEnumerable<Person> - вы возвращаете person as Person, который будет нулевым, потому что эта последовательность не на самом деле экземпляр Person.Если бы вы использовали приведение вместо as, вы бы видели это раньше - но сам факт того, что вы должны были сделать что-нибудь с типами, должно быть предупреждением о том, что вы не совсемделать правильные вещи.

Я подозреваю, что вы действительно хотите либо это:

public static IEnumerable<Person> ReadPeople(xmlpath)
{
    XDocument xd = XDocument.Load(xmlpath);
    return from p in xd.Descendants("person")
           select new Person
           {
               FirstName = p.Element("firstname").value,
               LastName = p.Element("lastname").value
           });
}

или это:

public static Person ReadPerson(xmlpath)
{
    XDocument xd = XDocument.Load(xmlpath);
    XElement element = xd.Descendants("person").First();
    return new Person
           {
               FirstName = element.Element("firstname").value,
               LastName = element.Element("lastname").value
           });
}

Вы должны также рассмотреть, что вы хотите, еслиЕсть нет person элементов или несколько элементов персонажа.Методы First, FirstOrDefault, Single и SingleOrDefault будут вам полезны здесь.

2 голосов
/ 25 мая 2011

Из того, как я это прочитал, все, что вам нужно, это:

public static IEnumerable<Person> ReadPeople(xmlpath)
{
    XDocument xd = XDocument.Load(xmlpath);
    return (from p in xd.Descendants("person")
            select new Person
            {
                FirstName = (string)p.Element("firstname"),
                LastName = (string)p.Element("lastname")
            });
}

Этот адрес:

  • вопрос о возвращении нескольких потомков
  • проблема с указанием имени / фамилии

если вы намереваетесь использовать только один, используйте Single() / First() / SingleOrDefault() / FirstOrDefault().

0 голосов
/ 25 мая 2011

В следующей строке есть проблема с неверным приведением.Вы должны позволить компилятору помочь вам (см. Мою измененную функцию).

return person as Person;

Вы должны вернуть список людей, а не только одного человека.Если вы уверены, что в xml присутствует только один человек, вы можете вызвать Single () вместо ToList ().

public static List<Person> ReadPerson(xmlpath)
{
    XDocument xd = XDocument.Load(xmlpath);
    /*var person = (from p in xd.Descendants("person")
                  select new Person
                  {
                      FirstName = p.Element("firstname").value,
                      LastName = p.Element("lastname").value
                  });*/
    List<Person> persons = (from p in xd.Descendants("person")
                  select new Person
                  {
                      FirstName = p.Element("firstname").value,
                      LastName = p.Element("lastname").value
                  }).ToList();
    return persons;
}
0 голосов
/ 25 мая 2011

Я вижу проблему! person в методе ReadPerson не является экземпляром класса Person, но коллекция (IEnumerable<Person>) и приведение к Person возвращают null.

...