开发者

return a class directly from a linq query

I'm still new to LINQ. Is it possible to do the following:

e.g., I have a class:

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

Now i want to return it as a class object by reading, say, an xml file's contents and returning it.

So if i read this xml file:

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

Read Person (say this belongs to a People class):

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

Now if i do the following elsewhere:

Person p = new Person();
p = People.Person(xmlpath);
Response.Write(p.FirstNam开发者_高级运维e);

Here, p.FirstName returns a null exception. Which i understand is because the linq query returned an empty class.

So my question is, is there anyway to directly add stuff into a class within a query and return it WITHOUT running a foreach loop and adding everything in manually? (like the following:)

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

Sorry if this is a stupid question.

Thanks


You need to distinguish between reading a sequence of items and reading a single item. Currently the person variable in ReadPerson is actually of type IEnumerable<Person> - you're returning person as Person which will be null, because that sequence isn't actually an instance of Person. If you'd used a cast instead of as, you'd have seen that earlier - but the very fact that you had to do anything to the types should be a warning that you weren't quite doing the right thing.

I suspect you actually want either this:

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

or this:

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

You should also consider what you want to happen if there are no person elements, or multiple person elements. The First, FirstOrDefault, Single and SingleOrDefault methods will be useful for you here.


From how I read it, all you need is:

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

This addresses:

  • the issue of returning multiple descendants
  • the issue of firstname/lastname not being specified

if you intent there to only be one, then use Single() / First() / SingleOrDefault() / FirstOrDefault().


I see the problem! person in ReadPerson method is not instance of Person class, but collection (IEnumerable<Person>) and casting to Person returns null.


The following line has the invalid casting problem. You should let the compiler to help you (see my modified function).

return person as Person;

You should return a list of persons instead of just a single person. If you are sure that only one person is in the xml, you can call Single() instead of 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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜