How can I use a class as a data model in querying

2019-06-06 02:21发布

问题:

I have an Xml document:

<?xml version="1.0" encoding="utf-8"?>
<Family xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Person member="father" id="0">
    <Surname>Smith</Surname>
    <Forename>Robert</Forename>
      <Person member="son" id="1">
        <Surname>Smith</Surname>
        <Forename>Sam</Forename>
          <Person member="son" id="2">
            <Surname>Smith</Surname>
            <Forename>Jeff</Forename>
          </Person>
      </Person>
      <Person member="daughter" id="3">
        <Surname>Smith</Surname>
        <Forename>Sarah</Forename>
      </Person>
  </Person>
</Family>

...and a few supporting classes as follows:

   [XmlRoot]
   public class Family {

      [XmlElement]
      public List<Person> Person;
   }

   public class Person {

      [XmlAttribute("member")]
      public MemberType Member { get; set; }

      [XmlAttribute("id")]
      public int Id { get; set; }

      [XmlElement]
      public string Surname { get; set; }

      [XmlElement]
      public string Forename { get; set; }

      [XmlElement("Person")]
      public List<Person> People;
   }

   public enum MemberType {
      Father,
      Mother,
      Son,
      Daughter
   }

Now, say Family has a method defined as such:

public IEnumerable<Person> Find (Func<Person, bool> predicate) {
    //  also, I know that this SelectMany will not work - assume this foreach works
    //  on a flattened list of people
    foreach (var p in family.Person.SelectMany()) {
        if(predicate(p)) {
            yield return p;
        }
    }
}

...but I don't want to deserialize the Xml to the Family and Person classes. I would like to simply load the XDocument and query that directly - but working with XElement, XAttribute, and XName is not that friendly when providing an API. I realize that I need the classes - Family & Person - but they are simply models.

Can I have a Find method where I can pass something like:

IEnumerable<Person> people = someBusinessObj.Find(p => p.Forename == "Jeff");

Update
I would prefer a solution that does not involve an open-source project (as @MartinHonnen refers).

回答1:

Why do you not want to deserialize the XML into objects? This will give you exactly the programmatic interface you require. I would:

  1. Deserialize using the XmlSerializer class.
  2. Allow you users to query via Linq-to-Objects.

All this requires very little effort to implement!