Setelah seorang programmer memutuskan untuk mengimplementasikan IXmlSerializable
, apa aturan dan praktik terbaik untuk mengimplementasikannya? Saya pernah mendengar bahwa GetSchema()
harus kembali null
dan ReadXml
harus pindah ke elemen berikutnya sebelum kembali. Apakah ini benar? Dan bagaimana WriteXml
- haruskah menulis elemen root untuk objek atau diasumsikan bahwa root sudah ditulis? Bagaimana seharusnya benda-benda anak diperlakukan dan ditulis?
Ini contoh dari apa yang saya miliki sekarang. Saya akan memperbaruinya karena saya mendapat respons yang baik.
public class MyCalendar : IXmlSerializable
{
private string _name;
private bool _enabled;
private Color _color;
private List<MyEvent> _events = new List<MyEvent>();
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyCalendar")
{
_name = reader["Name"];
_enabled = Boolean.Parse(reader["Enabled"]);
_color = Color.FromArgb(Int32.Parse(reader["Color"]));
if (reader.ReadToDescendant("MyEvent"))
{
while (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyEvent")
{
MyEvent evt = new MyEvent();
evt.ReadXml(reader);
_events.Add(evt);
}
}
reader.Read();
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("Name", _name);
writer.WriteAttributeString("Enabled", _enabled.ToString());
writer.WriteAttributeString("Color", _color.ToArgb().ToString());
foreach (MyEvent evt in _events)
{
writer.WriteStartElement("MyEvent");
evt.WriteXml(writer);
writer.WriteEndElement();
}
}
}
public class MyEvent : IXmlSerializable
{
private string _title;
private DateTime _start;
private DateTime _stop;
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader)
{
if (reader.MoveToContent() == XmlNodeType.Element && reader.LocalName == "MyEvent")
{
_title = reader["Title"];
_start = DateTime.FromBinary(Int64.Parse(reader["Start"]));
_stop = DateTime.FromBinary(Int64.Parse(reader["Stop"]));
reader.Read();
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("Title", _title);
writer.WriteAttributeString("Start", _start.ToBinary().ToString());
writer.WriteAttributeString("Stop", _stop.ToBinary().ToString());
}
}
XML Sampel yang Sesuai
<MyCalendar Name="Master Plan" Enabled="True" Color="-14069085">
<MyEvent Title="Write Code" Start="-8589241828854775808" Stop="-8589241756854775808" />
<MyEvent Title="???" Start="-8589241828854775808" Stop="-8589241756854775808" />
<MyEvent Title="Profit!" Start="-8589247048854775808" Stop="-8589246976854775808" />
</MyCalendar>
c#
xml
xml-serialization
Greg
sumber
sumber
Jawaban:
Ya, GetSchema () harus mengembalikan nol .
Untuk membaca dan menulis, elemen objek sudah ditulis, jadi Anda tidak perlu menambahkan elemen luar dalam tulis. Misalnya, Anda bisa mulai membaca / menulis atribut di keduanya.
Untuk menulis :
Dan untuk dibaca :
Saya akan setuju bahwa ini sedikit tidak jelas, tetapi intinya adalah "itu adalah tugas Anda untuk
Read()
tag elemen akhir pembungkus".sumber
Saya menulis satu artikel tentang subjek dengan sampel sebagai dokumentasi MSDN sekarang cukup jelas dan contoh-contoh yang Anda temukan di web sebagian besar waktu salah diimplementasikan.
Perangkap adalah penanganan lokal dan elemen kosong di samping apa yang telah disebutkan Marc Gravell.
http://www.codeproject.com/KB/XML/ImplementIXmlSerializable.aspx
sumber
Ya, semuanya sedikit seperti ladang ranjau, bukan? Jawaban Marc Gravell cukup banyak membahasnya, tetapi saya ingin menambahkan bahwa dalam proyek yang saya kerjakan kami merasa agak canggung harus secara manual menulis elemen XML luar. Ini juga menghasilkan nama elemen XML yang tidak konsisten untuk objek dengan tipe yang sama.
Solusi kami adalah mendefinisikan
IXmlSerializable
antarmuka kami sendiri , yang berasal dari sistem, yang menambahkan metode yang disebutWriteOuterXml()
. Seperti yang bisa Anda tebak, metode ini hanya akan menulis elemen luar, lalu memanggilWriteXml()
, lalu menulis akhir elemen. Tentu saja, serializer sistem XML tidak akan memanggil metode ini, jadi itu hanya berguna ketika kami melakukan serialisasi sendiri, sehingga mungkin atau mungkin tidak membantu dalam kasus Anda. Demikian pula, kami menambahkanReadContentXml()
metode, yang tidak membaca elemen luar, hanya isinya.sumber
Jika Anda sudah memiliki representasi XmlDocument dari kelas Anda atau lebih suka cara XmlDocument bekerja dengan struktur XML, cara cepat dan kotor mengimplementasikan IXmlSerializable adalah dengan hanya meneruskan xmldoc ini ke berbagai fungsi.
PERINGATAN: XmlDocument (dan / atau XDocument) adalah urutan besarnya lebih lambat dari xmlreader / penulis, jadi jika kinerja merupakan persyaratan mutlak, solusi ini bukan untuk Anda!
sumber
Implementasi antarmuka tercakup oleh jawaban lain, tetapi saya ingin melemparkan 2-sen saya untuk elemen root.
Saya telah belajar di masa lalu untuk lebih suka menempatkan elemen root sebagai metadata. Ini memiliki beberapa manfaat:
Di bawah ini adalah contoh dari kamus berseri serial di mana elemen root kamus didefinisikan dengan cara itu:
sumber