Je désérialise à partir d'un fichier xml en utilisant XmlSerializer sur des classes générées par Xsd2Code à partir d'un fichier xsd avec des éléments étendant un élément de base.Impossible de désérialiser la liste polymorphe à partir de xml
Voici un exemple simplifié:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Vehicle" abstract="true">
<xs:sequence>
<xs:element name="Manufacturer" type="xs:string" nillable="false" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Car">
<xs:complexContent>
<xs:extension base="Vehicle">
<xs:sequence>
<xs:element name="Configuration" type="xs:string" nillable="false" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="Truck">
<xs:complexContent>
<xs:extension base="Vehicle">
<xs:sequence>
<xs:element name="Load" type="xs:int" nillable="false" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Garage">
<xs:complexType>
<xs:sequence>
<xs:element name="Vehicles" type="Vehicle" minOccurs="0" maxOccurs="unbounded" nillable="false" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Code généré:
public partial class Garage
{
public Garage()
{
Vehicles = new List<Vehicle>();
}
public List<Vehicle> Vehicles { get; set; }
}
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Truck))]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Car))]
public partial class Vehicle
{
public string Manufacturer { get; set; }
}
public partial class Truck : Vehicle
{
public int Load { get; set; }
}
public partial class Car : Vehicle
{
public string Configuration { get; set; }
}
Le XML:
<?xml version="1.0" encoding="utf-8" ?>
<Garage>
<Vehicles>
<Vehicle>
<Manufacturer>Honda</Manufacturer>
<Configuration>Sedan</Configuration>
</Vehicle>
<Vehicle>
<Manufacturer>Volvo</Manufacturer>
<Load>40</Load>
</Vehicle>
</Vehicles>
</Garage>
Et le code désérialisation:
var sérialiseur = new XmlSeria lizer (typeof (Garage));
using (var reader = File.OpenText("Settings.xml"))
{
var garage = (Garage)serializer.Deserialize(reader);
var car = garage.Vehicles[0] as Car;
Console.WriteLine(car.Configuration);
}
je reçois une exception The specified type is abstract: name='Vehicle', namespace='', at <Vehicle xmlns=''>.
sur la ligne de désérialisation.
Si je supprime l'attribut abstrait de l'élément Vehicle dans XSD, j'obtiens une exception de référence nulle car garage.Vehicles[0]
ne peut pas être converti en Car
. Je veux être en mesure de désérialiser puis de lancer Car
et Truck
. Comment puis-je faire ce travail?
Merci pour la réponse. En effet, il y a un problème d'imbrication que j'ai négligé lors de l'ajout de cet exemple simplifié, le vrai code a le bon niveau d'imbrication dans xsd et xml. J'ai finalement opté pour la même solution xsi: type que vous avez suggérée. Cela fonctionne très bien pour moi car mon xml contient une petite collection de "Véhicules", mais je me demande, que ferions-nous pour une énorme collection? Pourrait être un cauchemar d'entretien. – Dondey