基本要素を拡張する要素を持つxsdファイルからXsd2Codeによって生成されたクラスに対して、XmlSerializerを使用してXMLファイルから逆シリアル化します。ここでxmlからポリモーフィックリストを逆シリアル化できません
は簡単な例です:
<?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>
生成されたコード:
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; }
}
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>
そしてデシリアライズコード:新しい
するvarシリアライザ= XmlSeriaライザー(typeof(ガレージ));
using (var reader = File.OpenText("Settings.xml"))
{
var garage = (Garage)serializer.Deserialize(reader);
var car = garage.Vehicles[0] as Car;
Console.WriteLine(car.Configuration);
}
私はデシリアライズライン上の例外The specified type is abstract: name='Vehicle', namespace='', at <Vehicle xmlns=''>.
を取得します。
XSDのVehicle要素から抽象属性を削除すると、garage.Vehicles[0]
をCar
にキャストできないため、null参照例外が発生します。
デシリアライズしてからCar
とTruck
にキャストできます。どうすればこの作品を作れますか?
返信いただきありがとうございます。確かに、この単純化された例を追加する際に見落とされていた入れ子の問題があります。真のコードはxsdとxmlの両方で正しい入れ子レベルを持っています。私は最終的にあなたが提案した同じxsi:typeソリューションを選択しました。私のXMLは「Vehicles」の短いコレクションを保持しているので、これはうまく動作しますが、巨大なコレクションの場合はどうなりますか?メンテナンスの悪夢かもしれません。 – Dondey