De-serializing some XML (via a Stream) into Parent/Child objects
I have a fairly simple DAL assembly that consists of an SalesEnquiry
Class which contains a List<T>
of another Vehicle
class.
We'll be receiving XML files by email that I'm wanting to use to populate instances of my SalesEnquiry class, so I'm trying to use de-serialization.
I've added XMLRoot
/XMLElement
/XMLIgnore
attributes to both classes as I think is appropriate. However, when I try de-serializing, the parent SalesEnquiry object is populated but no child Vehicle objects.
I understand that de-serializing List<T>
can be tricky, but I'm not sure why, how to avoid problems, or even if this is why I'm struggling.
While debugging, I've successfully serialized a Vehicle object on it's own, so I'm assuming that I'm heading in the right direction, but when I de-serialize the SalesEnquiry XML (which contains one or more child Vehicles), the List<Vehicle>
isn't populated.
Where am I going wrong?
Update:
In a test project, I serialized an SalesEnquiry
containing two vehicles and save to a file. I then loaded the file up an de-serialized it back into a different SalesEnquiry
object. It worked!
So what was the difference? The vehicles were recorded as follows:
<?xml version="1.0" encoding="utf-8"?>
<enquiry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<enquiry_no>100001</enquiry_no>
<vehicles>
<Vehicle>
<vehicle_type>Car</vehicle_type>
<vehicle_make>Ford</vehicle_make>
<vehicle_model>C-Max</vehicle_model>
...
The thing to note is that Vehicle has a an initial capital, whereas my incoming XML doesn't. In my Vehicle
class, I gave the class an [XmlRoot("vehicle")]
attribute, which I though would make the link, but clearly it doesn't. This makes sense, I guess, because although Vehicle is a class in it's own right, it's merely an array item within a List inside my SalesEnquiry.
In which case, the question is - How do I annotate the Vehicle
class such that I can map the incoming XML elements (<vehicle>
) to my list items (Vehicle
)? [XmlArrayItem]
(or [XmlElement]
for that matter) are 'not valid on this declaration type'.
In this example, I can request that the people who generate the XML use <Vehicle>
rather than <vehicle>
, but开发者_Python百科 there may be situations where I don't have this freedom, so I'd rather learn a solution than apply a workaround.
Conclusion:
By adding [XmlArrayItem("vehicle", typeof(Vehicle))] to the existing decoration for my List, the XML is now able to de-serialize fully. Phew!
Here's a working pair of classes with appropriate decorations:
(Note: The XmlAnyElement and XmlAnyAttribute are optional. It's a habit I'm in to promote the flexibility of the entity.)
[XmlType("enquiry")]
[XmlRoot("enquiry")]
public class Enquiry
{
private List<Vehicle> vehicles = new List<Vehicle>();
[XmlElement("enquiry_no")]
public int EnquiryNumber { get; set; }
[XmlArray("vehicles")]
[XmlArrayItem("Vehicle", typeof(Vehicle))]
public List<Vehicle> Vehicles
{
get { return this.vehicles; }
set { this.vehicles = value ?? new List<Vehicle>(); }
}
[XmlAnyElement]
public XmlElement[] AnyElements;
[XmlAnyAttribute]
public XmlAttribute[] AnyAttributes;
}
public class Vehicle
{
[XmlElement("vehicle_type")]
public string VehicleType { get; set; }
[XmlElement("vehicle_make")]
public string VehicleMake { get; set; }
[XmlElement("vehicle_model")]
public string VehicleModel { get; set; }
}
精彩评论