Saya mengalami beberapa masalah saat melakukan serialisasi C # XML yang saya pikir akan saya bagikan:
- Anda tidak dapat membuat serial item yang bersifat read-only (seperti KeyValuePairs)
- Anda tidak dapat membuat serial kamus umum. Sebagai gantinya, coba kelas pembungkus ini (dari http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx ):
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
bool wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
return;
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement("item");
reader.ReadStartElement("key");
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("value");
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
this.Add(key, value);
reader.ReadEndElement();
reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
foreach (TKey key in this.Keys)
{
writer.WriteStartElement("item");
writer.WriteStartElement("key");
keySerializer.Serialize(writer, key);
writer.WriteEndElement();
writer.WriteStartElement("value");
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
Adakah gotchas Serialisasi XML lain di luar sana?
c#
xml-serialization
kurious
sumber
sumber
Jawaban:
Gotcha besar lainnya: saat mengeluarkan XML melalui halaman web (ASP.NET), Anda tidak ingin menyertakan Unicode Byte-Order Mark . Tentunya cara menggunakan atau tidak menggunakan BOM hampir sama:
BURUK (termasuk BOM):
BAIK:
Anda dapat secara eksplisit memberikan false untuk menunjukkan bahwa Anda tidak menginginkan BOM. Perhatikan perbedaan yang jelas dan nyata antara
Encoding.UTF8
danUTF8Encoding
.Tiga BOM Bytes tambahan di awal adalah (0xEFBBBF) atau (239 187 191).
Referensi: http://chrislaco.com/blog/troubleshooting-common-problems-with-the-xmlserializer/
sumber
XmlTextWriter
di .NET 2.0 atau lebih tinggi.Saya belum bisa memberikan komentar, jadi saya akan mengomentari postingan Dr8k dan melakukan observasi lagi. Variabel privat yang diekspos sebagai properti pengambil / penyetel publik, dan mendapatkan serial / deserialisasi seperti itu melalui properti tersebut. Kami melakukannya di pekerjaan lama saya setiap saat.
Satu hal yang perlu diperhatikan adalah bahwa jika Anda memiliki logika di properti tersebut, logika tersebut dijalankan, jadi terkadang, urutan serialisasi sebenarnya penting. Anggotanya adalah implisit diurutkan berdasarkan bagaimana mereka diurutkan dalam kode, tetapi tidak ada jaminan, terutama saat Anda mewarisi objek lain. Memesannya secara eksplisit adalah menyebalkan.
Saya pernah terbakar oleh ini di masa lalu.
sumber
Saat membuat serialisasi menjadi string XML dari aliran memori, pastikan untuk menggunakan MemoryStream # ToArray () sebagai ganti MemoryStream # GetBuffer () atau Anda akan berakhir dengan karakter sampah yang tidak akan melakukan deserialisasi dengan benar (karena buffer tambahan dialokasikan).
http://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer(VS.80).aspx
sumber
Jika serializer menemukan anggota / properti yang memiliki antarmuka sebagai tipenya, itu tidak akan membuat serial. Misalnya, berikut ini tidak akan membuat serial ke XML:
Meskipun ini akan membuat serial:
sumber
IEnumerables<T>
yang dihasilkan melalui pengembalian hasil tidak dapat diserialkan. Ini karena kompilator membuat kelas terpisah untuk mengimplementasikan pengembalian hasil dan kelas itu tidak ditandai sebagai dapat diserialkan.sumber
Anda tidak dapat membuat serial properti read-only. Anda harus memiliki pengambil dan penyetel, bahkan jika Anda tidak pernah berniat menggunakan deserialisasi untuk mengubah XML menjadi objek.
Untuk alasan yang sama, Anda tidak dapat membuat serial properti yang mengembalikan antarmuka: deserializer tidak akan tahu kelas konkret apa yang harus dibuat.
sumber
Oh, ini bagus: karena kode serialisasi XML dibuat dan ditempatkan di DLL terpisah, Anda tidak akan mendapatkan kesalahan yang berarti jika ada kesalahan dalam kode Anda yang merusak serializer. Hanya sesuatu seperti "tidak dapat menemukan s3d3fsdf.dll". Bagus.
sumber
Tidak dapat membuat serial objek yang tidak memiliki konstruktor tanpa parameter (baru saja digigit oleh yang itu).
Dan untuk beberapa alasan, dari properti berikut ini, Value menjadi serial, tetapi tidak FullName:
Saya tidak pernah sempat memikirkan mengapa, saya baru saja mengubah Nilai menjadi internal ...
sumber
double?
tapi hanyadouble
?null
dan oleh karena itu tidak akan menghasilkan XML apa pun saat diserialkanSatu hal lagi yang perlu diperhatikan: Anda tidak dapat membuat serial anggota kelas privat / dilindungi jika Anda menggunakan serialisasi XML "default".
Tetapi Anda dapat menentukan logika serialisasi XML kustom yang menerapkan IXmlSerializable di kelas Anda dan membuat serialisasi bidang privat yang Anda butuhkan / inginkan.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx
sumber
Jika rakitan yang dihasilkan Serialisasi XML Anda tidak dalam konteks Muat yang sama dengan kode yang mencoba menggunakannya, Anda akan mengalami kesalahan hebat seperti:
Penyebabnya bagi saya adalah plugin yang dimuat menggunakan konteks LoadFrom yang memiliki banyak kelemahan menggunakan konteks Load. Cukup menyenangkan melacak yang satu itu.
sumber
Anda mungkin menghadapi masalah membuat serial objek dengan tipe Color dan / atau Font.
Berikut adalah saran, yang membantu saya:
http://www.codeproject.com/KB/XML/xmlsettings.aspx
http://www.codeproject.com/KB/cs/GenericXmlSerializition.aspx
sumber
Lihat " Dukungan Pengikatan Atribut Bahasa Definisi Skema XML Lanjutan " untuk detail tentang apa yang didukung oleh XML Serializer, dan untuk detail tentang cara fitur XSD yang didukung didukung.
sumber
Jika Anda mencoba membuat serial array
List<T>
,, atauIEnumerable<T>
yang berisi instance subclass dariT
, Anda perlu menggunakan XmlArrayItemAttribute ke daftar semua subtipe yang digunakan. Jika tidak, Anda akan mendapatkan errorSystem.InvalidOperationException
saat runtime saat Anda membuat serial.Berikut adalah bagian dari contoh lengkap dari dokumentasi
sumber
Variabel / properti pribadi tidak diserialkan dalam mekanisme default untuk serialisasi XML, tetapi dalam serialisasi biner.
sumber
Properti yang ditandai dengan
Obsolete
atribut tidak berseri. Saya belum menguji denganDeprecated
atribut tetapi saya berasumsi itu akan bertindak dengan cara yang sama.sumber
Saya tidak bisa menjelaskan yang satu ini, tetapi saya menemukan ini tidak akan membuat serial:
tapi ini akan:
Dan juga perlu dicatat bahwa jika Anda melakukan serialisasi ke sebuah memstream, Anda mungkin ingin mencari 0 sebelum Anda menggunakannya.
sumber
Berhati-hatilah saat melakukan serialisasi tanpa serialisasi eksplisit, ini dapat menyebabkan penundaan saat .Net membangunnya. Saya menemukan ini baru-baru ini saat menserialisasikan RSAParameters .
sumber
Jika XSD Anda menggunakan grup substitusi, maka kemungkinan Anda tidak dapat (de) membuat serialisasi secara otomatis. Anda harus membuat pembuat serial Anda sendiri untuk menangani skenario ini.
Misalnya.
Dalam contoh ini, Amplop dapat berisi Pesan. Namun, serializer default .NET tidak membedakan antara Message, ExampleMessageA dan ExampleMessageB. Ini hanya akan membuat serial ke dan dari kelas Message dasar.
sumber
Saya percaya ini juga membuat Anda jika Anda mengekspos anggota privat melalui properti publik - anggota privat tidak diserialkan sehingga anggota publik semuanya mereferensikan nilai nol.
sumber