次のようにカスタムXML構造を作成したいと思います。
<Hotels>
<Hotel />
</Hotels>
これを実行できるようにするために、List
の実装を作成しました。私のコードは次のとおりです。
[XmlRootAttribute(ElementName="Hotels")]
public class HotelList: List<HotelBasic>
Listが保持するクラスの名前はHotel
ではなく、HotelBasic
なので、私のxmlは次のようになります。
<Hotels>
<HotelBasic />
</Hotels>
ISerializable
またはIEnumerable
を実装せずにこれを修正するにはどうすればよいですか?
XmlSerializer
を使用していると仮定して、HotelBasic
クラスのシリアル化方法を変更するだけの場合は、XmlTypeAttribute
を使用できます。
[XmlType(TypeName = "Hotel")]
public class HotelBasic
{
public string Name { get; set; }
}
HotelList
クラスで使用すると、次のようにシリアル化されます。
<Hotels xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Hotel>
<Name>One</Name>
</Hotel>
<Hotel>
<Name>Two</Name>
</Hotel>
</Hotels>
[XmlArray("Hotels")]
[XmlArrayItem(typeof(Hotel), ElementName="Hotel")]
public HotelList[] Messages { get; set; }
生成する必要があります:
<Hotels>
<Hotel />
<Hotel />
</Hotels>
[XmlRoot("Hotels")]
public class HotelList : IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
this.Hotels = XDocument.Load(reader)
.Select(h => new Hotel { Name = (string)h.Attribute("name") }
.ToList();
}
public void WriteXml(XmlWriter writer)
{
throw new NotSupportedException();
}
}
ここではmadd0が最も簡単なオプションを示していると思いますが、完全を期すために...個人的には「リストをルートオブジェクトとしてシリアル化する」ことはお勧めしません-さまざまな理由で(以下を含む:これらの属性が機能しないのを見たことがあります)少なくともプラットフォームでは-CFまたはSLであった可能性があり、覚えていません)。代わりに、カスタムルートタイプを使用することを常にお勧めします。
[XmlRoot("Hotels")]
public class HotelResult // or something similar
{
[XmlElement("Hotel")]
public List<HotelBasic> Hotels { get { return hotel; } }
private readonly List<HotelBasic> hotels = new List<HotelBasic>();
}
これは同じxml構造を持ち、柔軟性が高くなり(ルートに他の属性/要素を追加できます)、タイプモデルにList<T>
を焼き付けません(継承などよりもカプセル化を優先します)。