Mengapa properti tanpa penyetel tidak berseri

101

Saya memiliki kelas yang dapat diserialkan dan salah satu properti di kelas saya menghasilkan Guiddi pengambil. Properti tidak mengimplementasikan penyetel dan diabaikan selama serialisasi. Mengapa demikian dan apakah saya selalu harus menerapkan penyetel agar properti saya dapat diserialkan.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

Saya mencoba menerapkan penyetel kosong dan serialisasi dengan benar.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

Pembaruan :

Dapatkah Anda menunjukkan bagaimana saya harus mendefinisikan properti yang nilainya tidak pernah berubah atau yang nilainya dihasilkan secara internal?

Konstantin Dinev
sumber
1
Contoh kedua membuat serial dengan benar ... Tapi apa yang terjadi ketika Anda mencoba untuk menghilangkannya?
LightStriker
Coba YAXLib [+ , + ]
Sina Iravanian
3
FYI, XML Serializer mengabaikan [Serializable].
John Saunders
@JohnSaunders Saya tidak menyadarinya.
Konstantin Dinev

Jawaban:

60

Ini adalah batasannya XmlSerializertidak membuat serialisasi properti hanya-baca, apa yang telah Anda lakukan di contoh kedua Anda pada dasarnya adalah peretasan untuk membuatnya menjadi serial, namun, tidak ada gunanya jika Anda membutuhkannya untuk deserialisasi nanti.

Atau Anda dapat beralih menggunakan DataContractSerializer , ini lebih fleksibel.

James
sumber
8
DataContractSerializer juga membutuhkan penyetel. Ini adalah batasan karena meskipun kami dapat menggunakannya hanya untuk satu jenis operasi, katakanlah deserialization, tetapi deklarasi perlu untuk keduanya, proses serialisasi tidak akan tahu apa yang harus dilakukan dengan nilai ketika mencoba untuk membuat serialisasi XML menjadi objek.
ryadavilli
7
@ryadavilli segala sesuatu yang ditandai sebagai [DataMember]serial menggunakan DataContractSerializer(hanya-baca atau tidak).
Yakobus
1
@James Saya menulis di atas karena saya mendapat beberapa kesalahan waktu kompilasi ketika saya mencoba hal yang sama. Sekarang, ketika saya kembali ke kode saya dan menghapus penyetel, tampaknya kompilasi baik-baik saja. Ini sangat aneh dan mungkin pekerjaan rumah bagi saya untuk meneliti lebih lanjut tentang ini.
ryadavilli
3
Ahhh akhirnya menemukan sumber kebingunganku. Penyetel properti tidak diperlukan untuk serialisasi. Namun, jika properti tidak memiliki penyetel, XML tidak akan melakukan deserialisasi ke objek. Di sana, pekerjaan rumah selesai.
ryadavilli
1
@ryadavilli ya tepatnya, itu hanya batasan XmlSerializerimplementasinya, itu bergantung pada metode penyetel publik. DataContractSerializersedikit lebih pintar dalam hal itu (mungkin menggunakan refleksi untuk mengatur bidang di belakang layar).
Yakobus
10

Lihat " Memperkenalkan Serialisasi XML " dalam dokumentasi MSDN. Antara lain, dikatakan:

Item Yang Bisa Berseri

Item berikut dapat diserialkan menggunakan kelas XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

catatan:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

Selain itu, lihat " Mengapa kelas XML-Serializable membutuhkan konstruktor tanpa parameter "


Juga, IXmlSerializable

Selain jenis di atas yang dapat diserialkan oleh XML Serializer, jenis apa pun yang mengimplementasikan antarmuka IXmlSerializable dapat diserialisasi dan dideserialisasi. Secara khusus, ini berarti bahwa tipe XElement dan XDocument dapat diserialkan.

Lihat " IXmlSerializable Interface ".

John Saunders
sumber
6

Batasan XMLSerializer- Properti tanpa penyetel tidak dapat diserialkan.

Tapi Anda bisa menggunakan DataContractSerializeruntuk membuat serial private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Rohit Vats
sumber
Properti seharusnya berseri sebagai atribut-xml (lihat posting asli). Kode Anda (atribut DataMember) menghasilkan elemen xml. Sejauh yang saya tahu tidak ada cara (bersih) untuk memberi tahu DataContractSerializer untuk mengubah properti menjadi atribut dan bukan elemen. DataContractSerializer bagus tetapi Anda harus selalu mengingat batasan ini.
sth_Weird
2

jika Anda ingin memiliki penyetel pribadi, dan memiliki objek yang dapat diserialisasi / dideserialisasi, terapkan ISerializable, dan buat konstruktor seperti MyObject (info SerializationInfo, konteks StreamingContext). Sebuah contoh ditemukan di sini .

edamon
sumber
0

Atribut serialisasi digunakan untuk membuat serial dan deserialisasi objek. XmlSerializer akan menganggap bahwa Anda tidak perlu membuat serial properti apa pun yang tidak memiliki penyetel. Setter akan digunakan saat deserialisasi string menjadi objek, karena instance dari objek perlu dibuat dan kemudian setter akan digunakan untuk mengisi nilai properti.

Rui Jarimba
sumber