Serialisasi dan Deserialisasi

Windows Communication Foundation (WCF) mencakup mesin serialisasi baru, DataContractSerializer. DataContractSerializer menerjemahkan antara objek .NET Framework dan XML, dalam kedua arah. Topik ini menjelaskan cara kerja serializer.

Saat membuat serialisasi objek .NET Framework, serializer memahami berbagai model pemrograman serialisasi, termasuk model kontrak data baru. Untuk daftar lengkap jenis yang didukung, lihat Jenis yang Didukung oleh Serializer Kontrak Data. Untuk pengenalan kontrak data, lihat Menggunakan Kontrak Data.

Saat mendeserialisasi XML, serializer menggunakan kelas XmlReader dan XmlWriter. Ini juga mendukung XmlDictionaryReader kelas dan XmlDictionaryWriter untuk memungkinkannya menghasilkan XML yang dioptimalkan dalam beberapa kasus, seperti saat menggunakan format XML biner WCF.

WCF juga mencakup serializer pendamping, NetDataContractSerializer. NetDataContractSerializer:

  • Tidak aman. Untuk informasi selengkapnya, lihat panduan keamanan BinaryFormatter.
  • Mirip dengan serializer BinaryFormatter dan SoapFormatter karena juga mengeluarkan nama tipe .NET Framework sebagai bagian dari data yang diserialisasikan.
  • Digunakan ketika jenis yang sama dipakai di sisi serialisasi dan deserialisasi.

Baik DataContractSerializer dan NetDataContractSerializer berasal dari kelas dasar umum, XmlObjectSerializer.

Peringatan

DataContractSerializer men-serialisasi string yang berisi karakter kontrol bernilai heksadesimal di bawah 20 sebagai entitas XML. Ini dapat menyebabkan masalah dengan klien non-WCF saat mengirim data tersebut ke layanan WCF.

Membuat Instans DataContractSerializer

Membangun instans DataContractSerializer adalah langkah penting. Setelah konstruksi, Anda tidak dapat mengubah pengaturan apa pun.

Menentukan Jenis Akar

Tipe root adalah tipe yang instansnya diserialisasikan atau dideserialisasikan. DataContractSerializer memiliki banyak pemanggilan berlebih konstruktor, tetapi, minimal, tipe akar harus disediakan menggunakan parameter type.

Serializer yang dibuat untuk jenis induk tertentu tidak dapat digunakan untuk menserialisasikan atau mendeserialisasi tipe lain, kecuali tipe tersebut diturunkan dari jenis induk. Contoh berikut menunjukkan dua kelas.

[DataContract]
public class Person
{
    // Code not shown.
}

[DataContract]
public class PurchaseOrder
{
    // Code not shown.
}
<DataContract()> _
Public Class Person
    ' Code not shown.
End Class

<DataContract()> _
Public Class PurchaseOrder
    ' Code not shown.
End Class

Kode ini membangun instans DataContractSerializer yang hanya dapat digunakan untuk menserialisasikan atau mendeserialisasi instans Person kelas.

DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
// This can now be used to serialize/deserialize Person but not PurchaseOrder.
Dim dcs As New DataContractSerializer(GetType(Person))
' This can now be used to serialize/deserialize Person but not PurchaseOrder.

Menentukan Jenis yang Diketahui

Jika polimorfisme terlibat dalam jenis yang diserialisasi dan tidak ditangani oleh atribut KnownTypeAttribute atau mekanisme lain, daftar jenis yang diketahui harus diteruskan ke konstruktor serializer menggunakan parameter knownTypes. Untuk informasi selengkapnya tentang jenis yang diketahui, lihat Jenis Kontrak Data yang Diketahui.

Contoh berikut menunjukkan kelas, LibraryPatron, yang menyertakan koleksi jenis tertentu, LibraryItem. Kelas kedua mendefinisikan tipe LibraryItem. Kelas ketiga dan keempat (Book dan Newspaper) mewarisi dari kelas LibraryItem.

[DataContract]
public class LibraryPatron
{
    [DataMember]
    public LibraryItem[] borrowedItems;
}
[DataContract]
public class LibraryItem
{
    // Code not shown.
}

[DataContract]
public class Book : LibraryItem
{
    // Code not shown.
}

[DataContract]
public class Newspaper : LibraryItem
{
    // Code not shown.
}
<DataContract()> _
Public Class LibraryPatron
    <DataMember()> _
    Public borrowedItems() As LibraryItem
End Class

<DataContract()> _
Public Class LibraryItem
    ' Code not shown.
End Class

<DataContract()> _
Public Class Book
    Inherits LibraryItem
    ' Code not shown.
End Class

<DataContract()> _
Public Class Newspaper
    Inherits LibraryItem
    ' Code not shown.
End Class

Kode berikut membuat instans serializer menggunakan knownTypes parameter .

// Create a serializer for the inherited types using the knownType parameter.
Type[] knownTypes = new Type[] { typeof(Book), typeof(Newspaper) };
DataContractSerializer dcs =
new DataContractSerializer(typeof(LibraryPatron), knownTypes);
// All types are known after construction.
' Create a serializer for the inherited types using the knownType parameter.
Dim knownTypes() As Type = {GetType(Book), GetType(Newspaper)}
Dim dcs As New DataContractSerializer(GetType(LibraryPatron), knownTypes)
' All types are known after construction.

Menentukan Nama Akar Default dan Namespace

Biasanya, ketika objek diserialisasikan, nama default dan namespace elemen XML terluar ditentukan sesuai dengan nama kontrak data dan namespace layanan. Nama semua elemen internal ditentukan berdasarkan nama anggota data, dan namespace mereka adalah namespace dari kontrak data. Contoh berikut menetapkan nilai Name dan Namespace di konstruktor kelas DataContractAttribute dan DataMemberAttribute.

[DataContract(Name = "PersonContract", Namespace = "http://schemas.contoso.com")]
public class Person2
{
    [DataMember(Name = "AddressMember")]
    public Address theAddress;
}

[DataContract(Name = "AddressContract", Namespace = "http://schemas.contoso.com")]
public class Address
{
    [DataMember(Name = "StreetMember")]
    public string street;
}
<DataContract(Name:="PersonContract", [Namespace]:="http://schemas.contoso.com")> _
Public Class Person2
    <DataMember(Name:="AddressMember")> _
    Public theAddress As Address
End Class

<DataContract(Name:="AddressContract", [Namespace]:="http://schemas.contoso.com")> _
Public Class Address
    <DataMember(Name:="StreetMember")> _
    Public street As String
End Class

Men-serialkan contoh dari kelas Person menghasilkan XML yang serupa dengan contoh berikut.

<PersonContract xmlns="http://schemas.contoso.com">
  <AddressMember>
    <StreetMember>123 Main Street</StreetMember>
   </AddressMember>
</PersonContract>

Namun, Anda dapat menyesuaikan nama default dan namespace elemen akar dengan meneruskan nilai rootName parameter dan rootNamespace ke DataContractSerializer konstruktor. Perhatikan bahwa rootNamespace tidak memengaruhi namespace elemen yang terkandung yang sesuai dengan anggota data. Ini hanya memengaruhi namespace elemen terluar.

Nilai-nilai ini dapat diteruskan sebagai string atau instans XmlDictionaryString kelas untuk memungkinkan pengoptimalannya menggunakan format XML biner.

Mengatur Kuota Objek Maksimum

Beberapa DataContractSerializer kelebihan beban konstruktor memiliki maxItemsInObjectGraph parameter . Parameter ini menentukan jumlah maksimum objek yang diserialisasikan oleh penyusun serial atau dideserialisasikan dalam satu panggilan metode ReadObject. (Metode ini selalu membaca satu objek akar, tetapi objek ini mungkin memiliki objek lain dalam anggota datanya. Objek tersebut mungkin memiliki objek lain, dan sebagainya.) Defaultnya adalah 65536. Perhatikan bahwa saat menserialisasikan atau mendeserialisasi array, setiap entri array dihitung sebagai objek terpisah. Perhatikan juga bahwa beberapa objek mungkin memiliki representasi memori yang besar, sehingga kuota ini saja mungkin tidak cukup untuk mencegah penolakan serangan layanan. Untuk informasi selengkapnya, lihat Pertimbangan Keamanan untuk Data. Jika Anda perlu meningkatkan kuota ini di luar nilai default, penting untuk melakukannya baik pada sisi pengiriman (serialisasi) maupun penerimaan (deserialisasi) karena berlaku untuk saat membaca dan menulis data.

Pulang Pergi

Proses bolak-balik terjadi ketika objek dideserialisasi dan diserialisasikan ulang dalam satu operasi. Dengan demikian, ia beralih dari XML ke instans objek, dan kembali lagi ke aliran XML.

Beberapa DataContractSerializer overload konstruktor memiliki ignoreExtensionDataObject parameter, yang diatur ke false secara default. Dalam mode default ini, data dapat dikirim pada perjalanan pulang pergi dari versi kontrak data yang lebih baru melalui versi yang lebih lama dan kembali ke versi yang lebih baru tanpa kehilangan, selama kontrak data mengimplementasikan IExtensibleDataObject antarmuka. Misalnya, versi 1 dari kontrak data Person berisi anggota data Name dan PhoneNumber, dan versi 2 menambahkan anggota Nickname. Jika IExtensibleDataObject diimplementasikan, saat mengirim informasi dari versi 2 ke versi 1, Nickname data disimpan, lalu dipancarkan kembali ketika data diserialisasikan lagi; oleh karena itu, tidak ada data yang hilang dalam perjalanan pulang pergi. Untuk informasi selengkapnya, lihat Forward-Compatible Kontrak Data dan Penerapan Versi Kontrak Data.

Masalah Keamanan dan Validitas Skema dengan Perjalanan Pulang Pergi

Perjalanan pulang pergi mungkin memiliki implikasi keamanan. Misalnya, deserialisasi dan penyimpanan data asing dalam jumlah besar mungkin merupakan risiko keamanan. Mungkin ada kekhawatiran keamanan tentang penyiaran ulang data ini yang tidak memiliki cara untuk diverifikasi, terutama jika tanda tangan digital terlibat. Misalnya, dalam skenario sebelumnya, endpoint versi 1 dapat menandatangani nilai Nickname yang berisi data berbahaya. Akhirnya, mungkin ada masalah validitas skema: titik akhir mungkin ingin selalu memancarkan data yang secara ketat mematuhi kontrak yang dinyatakan dan bukan nilai tambahan. Dalam contoh sebelumnya, kontrak titik akhir versi 1 menyatakan bahwa ia hanya memancarkan Name dan PhoneNumber, dan jika validasi skema sedang digunakan, pengeluaran nilai tambahan Nickname menyebabkan validasi gagal.

Mengaktifkan dan Menonaktifkan Siklus Bolak-Balik

Untuk menonaktifkan perjalanan pulang pergi, jangan terapkan IExtensibleDataObject antarmuka. Jika Anda tidak memiliki kontrol atas jenis, atur parameter ignoreExtensionDataObject ke true untuk mencapai efek yang sama.

Pemeliharaan Graf Objek

Biasanya, serializer tidak peduli tentang identitas objek, seperti dalam kode berikut.

[DataContract]
public class PurchaseOrder
{
    [DataMember]
    public Address billTo;
    [DataMember]
    public Address shipTo;
}

[DataContract]
public class Address
{
    [DataMember]
    public string street;
}
<DataContract()> _
Public Class PurchaseOrder

    <DataMember()> _
    Public billTo As Address

    <DataMember()> _
    Public shipTo As Address

End Class

<DataContract()> _
Public Class Address

    <DataMember()> _
    Public street As String

End Class

Kode berikut membuat pesanan pembelian.

// Construct a purchase order:
Address adr = new Address();
adr.street = "123 Main St.";
PurchaseOrder po = new PurchaseOrder();
po.billTo = adr;
po.shipTo = adr;
' Construct a purchase order:
Dim adr As New Address()
adr.street = "123 Main St."
Dim po As New PurchaseOrder()
po.billTo = adr
po.shipTo = adr

Perhatikan bahwa field billTo dan shipTo disetel pada instans objek yang sama. Namun, XML yang dihasilkan menduplikasi informasi yang diduplikasi, dan terlihat mirip dengan XML berikut.

<PurchaseOrder>
  <billTo><street>123 Main St.</street></billTo>
  <shipTo><street>123 Main St.</street></shipTo>
</PurchaseOrder>

Namun, pendekatan ini memiliki karakteristik berikut, yang mungkin tidak diinginkan:

  • Performa. Mereplikasi data tidak efisien.

  • Referensi melingkar. Jika objek merujuk pada diri mereka sendiri, bahkan melalui objek lain, serialisasi dengan replikasi menghasilkan perulangan tak terbatas. (Serializer melempar sebuah SerializationException jika ini terjadi.)

  • Semantik. Terkadang penting untuk mempertahankan fakta bahwa dua referensi adalah ke objek yang sama, dan bukan ke dua objek yang identik.

Untuk alasan ini, beberapa DataContractSerializer kelebihan beban konstruktor memiliki preserveObjectReferences parameter (defaultnya adalah false). Ketika parameter ini diatur ke true, metode khusus untuk mengodekan referensi objek, yang hanya dipahami WCF, yang digunakan. Saat diatur ke true, contoh kode XML sekarang menyerupai berikut ini.

<PurchaseOrder ser:id="1">
  <billTo ser:id="2"><street ser:id="3">123 Main St.</street></billTo>
  <shipTo ser:ref="2"/>
</PurchaseOrder>

Namespace "ser" mengacu pada namespace serialisasi standar, http://schemas.microsoft.com/2003/10/Serialization/. Setiap bagian data diserialisasikan hanya sekali dan diberi nomor ID, dan penggunaan berikutnya menghasilkan referensi ke data yang sudah diserialisasikan.

Penting

Jika atribut "id" dan "ref" ada dalam kontrak XMLElementdata , atribut "ref" akan dihormati dan atribut "id" diabaikan.

Penting untuk memahami batasan mode ini:

  • XML yang dihasilkan oleh DataContractSerializer dengan preserveObjectReferences diatur ke true tidak dapat beroperasi bersamaan dengan teknologi lain, dan hanya dapat diakses oleh instans DataContractSerializer lain, yang juga memiliki preserveObjectReferences diatur ke true.

  • Tidak ada dukungan metadata (skema) untuk fitur ini. Skema yang diproduksi hanya berlaku untuk kasus ketika preserveObjectReferences diatur ke false.

  • Fitur ini dapat menyebabkan proses serialisasi dan deserialisasi berjalan lebih lambat. Meskipun data tidak harus direplikasi, perbandingan objek tambahan harus dilakukan dalam mode ini.

Perhatian

Ketika mode preserveObjectReferences diaktifkan, sangat penting untuk mengatur nilai maxItemsInObjectGraph ke kuota yang benar. Karena cara array ditangani dalam mode ini, seorang penyerang dapat dengan mudah membuat pesan berbahaya kecil yang mengakibatkan konsumsi memori besar yang hanya dibatasi oleh kuota maxItemsInObjectGraph.

Menentukan Pengganti Kontrak Data

Beberapa DataContractSerializer kelebihan beban konstruktor memiliki dataContractSurrogate parameter, yang dapat diatur ke null. Jika tidak, Anda dapat menggunakannya untuk menentukan pengganti kontrak data, yang merupakan jenis yang mengimplementasikan IDataContractSurrogate antarmuka. Anda kemudian dapat menggunakan antarmuka untuk menyesuaikan proses serialisasi dan deserialisasi. Untuk informasi selengkapnya, lihat Data Contract Surrogates (Pengganti Kontrak Data).

Serialisasi

Informasi berikut berlaku untuk kelas apa pun yang mewarisi dari XmlObjectSerializer, termasuk DataContractSerializer kelas dan NetDataContractSerializer .

Serialisasi Sederhana

Cara paling mendasar untuk menserialisasikan objek adalah dengan meneruskannya ke WriteObject metode . Ada tiga kelebihan beban, masing-masing satu untuk menulis ke Stream, , XmlWriteratau XmlDictionaryWriter. Stream Dengan kelebihan beban, outputnya adalah XML dalam pengodean UTF-8. XmlDictionaryWriter Dengan kelebihan beban, serializer mengoptimalkan outputnya untuk XML biner.

Saat menggunakan metode WriteObject, seorang serializer menggunakan nama dan namespace default untuk elemen pembungkus dan menuliskannya bersama dengan isinya (lihat bagian "Menentukan Nama Akar dan Namespace Default" sebelumnya).

Contoh berikut menunjukkan penulisan dengan XmlDictionaryWriter.

Person p = new Person();
DataContractSerializer dcs =
    new DataContractSerializer(typeof(Person));
XmlDictionaryWriter xdw =
    XmlDictionaryWriter.CreateTextWriter(someStream,Encoding.UTF8 );
dcs.WriteObject(xdw, p);
Dim p As New Person()
Dim dcs As New DataContractSerializer(GetType(Person))
Dim xdw As XmlDictionaryWriter = _
    XmlDictionaryWriter.CreateTextWriter(someStream, Encoding.UTF8)
dcs.WriteObject(xdw, p)

Ini menghasilkan XML yang mirip dengan yang berikut ini.

<Person>
  <Name>Jay Hamlin</Name>
  <Address>123 Main St.</Address>
</Person>

Langkah- serialisasiBy-Step

WriteStartObjectGunakan metode , WriteObjectContent, dan WriteEndObject untuk menulis elemen akhir, menulis konten objek, dan menutup elemen pembungkus, masing-masing.

Nota

Tidak ada Stream kelebihan beban metode ini.

Serialisasi langkah demi langkah ini memiliki dua kegunaan umum. Salah satunya adalah menyisipkan konten seperti atribut atau komentar antara WriteStartObject dan WriteObjectContent, seperti yang ditunjukkan dalam contoh berikut.

dcs.WriteStartObject(xdw, p);
xdw.WriteAttributeString("serializedBy", "myCode");
dcs.WriteObjectContent(xdw, p);
dcs.WriteEndObject(xdw);
dcs.WriteStartObject(xdw, p)
xdw.WriteAttributeString("serializedBy", "myCode")
dcs.WriteObjectContent(xdw, p)
dcs.WriteEndObject(xdw)

Ini menghasilkan XML yang mirip dengan yang berikut ini.

<Person serializedBy="myCode">
  <Name>Jay Hamlin</Name>
  <Address>123 Main St.</Address>
</Person>

Penggunaan umum lainnya adalah menghindari penggunaan WriteStartObject dan WriteEndObject sepenuhnya, dan untuk menulis elemen pembungkus kustom Anda sendiri (atau bahkan melewati penulisan pembungkus sama sekali), seperti yang ditunjukkan dalam kode berikut.

xdw.WriteStartElement("MyCustomWrapper");
dcs.WriteObjectContent(xdw, p);
xdw.WriteEndElement();
xdw.WriteStartElement("MyCustomWrapper")
dcs.WriteObjectContent(xdw, p)
xdw.WriteEndElement()

Ini menghasilkan XML yang mirip dengan yang berikut ini.

<MyCustomWrapper>
  <Name>Jay Hamlin</Name>
  <Address>123 Main St.</Address>
</MyCustomWrapper>

Nota

Menggunakan serialisasi langkah demi langkah dapat mengakibatkan XML yang tidak sesuai dengan skema.

Deserialisasi

Informasi berikut berlaku untuk kelas apa pun yang mewarisi dari XmlObjectSerializer, termasuk DataContractSerializer kelas dan NetDataContractSerializer .

Cara paling dasar untuk mendeserialisasi objek adalah dengan memanggil salah satu overload metode ReadObject. Ada tiga kelebihan beban, masing-masing satu untuk membaca dengan XmlDictionaryReader, , XmlReaderatau Stream. Perhatikan bahwa overload Stream menghasilkan teks XmlDictionaryReader yang tidak dilindungi oleh batas apa pun, dan harus digunakan hanya untuk membaca data yang tepercaya.

Perhatikan juga bahwa objek yang dikembalikan oleh metode ReadObject harus di-casting ke jenis yang sesuai.

Kode berikut membuat instans DataContractSerializer dan XmlDictionaryReader, lalu mendeserialisasi instans Person .

DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());

Person p = (Person)dcs.ReadObject(reader);
Dim dcs As New DataContractSerializer(GetType(Person))
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = _
   XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())

Dim p As Person = CType(dcs.ReadObject(reader), Person)

Sebelum memanggil ReadObject metode , posisikan pembaca XML pada elemen pembungkus atau pada node non-konten yang mendahului elemen pembungkus. Anda dapat melakukannya dengan memanggil metode Read dari XmlReader atau turunannya, serta menguji NodeType, seperti yang ditunjukkan dalam kode berikut.

DataContractSerializer ser = new DataContractSerializer(typeof(Person),
"Customer", @"http://www.contoso.com");
FileStream fs = new FileStream(path, FileMode.Open);
XmlDictionaryReader reader =
XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
while (reader.Read())
{
    switch (reader.NodeType)
    {
        case XmlNodeType.Element:
            if (ser.IsStartObject(reader))
            {
                Console.WriteLine("Found the element");
                Person p = (Person)ser.ReadObject(reader);
                Console.WriteLine($"{p.Name} {p.Address}    id:{2}");
            }
            Console.WriteLine(reader.Name);
            break;
    }
}
Dim ser As New DataContractSerializer(GetType(Person), "Customer", "http://www.contoso.com")
Dim fs As New FileStream(path, FileMode.Open)
Dim reader As XmlDictionaryReader = XmlDictionaryReader.CreateTextReader(fs, New XmlDictionaryReaderQuotas())

While reader.Read()
    Select Case reader.NodeType
        Case XmlNodeType.Element
            If ser.IsStartObject(reader) Then
                Console.WriteLine("Found the element")
                Dim p As Person = CType(ser.ReadObject(reader), Person)
                Console.WriteLine("{0} {1}", _
                                   p.Name, p.Address)
            End If
            Console.WriteLine(reader.Name)
    End Select
End While

Perhatikan bahwa Anda dapat membaca atribut pada elemen pembungkus ini sebelum menyerahkan pembaca ke ReadObject.

Saat menggunakan salah satu kelebihan beban sederhana ReadObject , deserializer mencari nama dan namespace default pada elemen pembungkus (lihat bagian sebelumnya, "Menentukan Nama Akar Default dan Namespace") dan melemparkan pengecualian jika menemukan elemen yang tidak diketahui. Dalam contoh sebelumnya, elemen <Person> pembungkus diharapkan. Metode IsStartObject ini dipanggil untuk memverifikasi bahwa pembaca diposisikan pada elemen yang dinamai seperti yang diharapkan.

Ada cara untuk menonaktifkan pemeriksaan nama elemen pembungkus ini; beberapa overload metode ReadObject mengambil parameter Boolean verifyObjectName, yang diatur ke true secara default. Ketika diatur ke false, nama dan namespace elemen pembungkus diabaikan. Ini berguna untuk membaca XML yang ditulis menggunakan mekanisme serialisasi langkah demi langkah yang dijelaskan sebelumnya.

Menggunakan NetDataContractSerializer

Perbedaan utama antara DataContractSerializer dan NetDataContractSerializer adalah bahwa DataContractSerializer menggunakan nama kontrak data, sementara NetDataContractSerializer menghasilkan rakitan .NET Framework lengkap dan nama tipe dalam XML yang diserialkan. Ini berarti bahwa jenis yang sama persis harus dibagi antara titik akhir serialisasi dan deserialisasi. Ini berarti bahwa mekanisme jenis yang telah dikenal tidak dibutuhkan ketika menggunakan NetDataContractSerializer karena jenis yang tepat untuk dideserialisasi selalu diketahui.

Namun, beberapa masalah dapat terjadi:

  • Keamanan. Jenis apa pun yang ditemukan dalam XML saat proses deserialisasi akan dimuat. Ini dapat dieksploitasi untuk memaksa pemuatan komponen berbahaya. Penggunaan NetDataContractSerializer dengan data yang tidak tepercaya hanya boleh dilakukan jika Serialization Binder digunakan, melalui properti atau parameter konstruktor Binder. Pengait hanya mengizinkan jenis yang aman untuk dimuat. Mekanisme Binder identik dengan yang digunakan oleh tipe dalam namespace System.Runtime.Serialization.

  • Penerapan versi. Menggunakan jenis lengkap dan nama rakitan di XML sangat membatasi bagaimana jenis dapat diberi versi. Berikut ini tidak dapat diubah: nama jenis, namespace, nama rakitan, dan versi rakitan. AssemblyFormat Mengatur parameter properti atau konstruktor ke Simple alih-alih nilai Full default memungkinkan perubahan versi rakitan, tetapi tidak untuk jenis parameter generik.

  • Interoperabilitas. Karena jenis .NET Framework dan nama rakitan disertakan dalam XML, platform selain .NET Framework tidak dapat mengakses data yang dihasilkan.

  • Performa. Menulis jenis dan nama rakitan secara signifikan meningkatkan ukuran XML yang dihasilkan.

Mekanisme ini mirip dengan serialisasi biner atau SOAP yang digunakan oleh .NET Framework remoting (khususnya, BinaryFormatter dan SoapFormatter).

NetDataContractSerializer Menggunakannya mirip dengan menggunakan DataContractSerializer, dengan perbedaan berikut:

  • Konstruktor tidak mengharuskan Anda menentukan jenis akar. Anda dapat menserialisasikan jenis apa pun dengan instans yang sama dari NetDataContractSerializer.

  • Konstruktor tidak menerima daftar jenis yang diketahui. Mekanisme jenis yang diketahui tidak perlu jika nama jenis diserialisasikan ke dalam XML.

  • Konstruktor tidak menerima pengganti kontrak data. Sebaliknya, mereka menerima parameter bernama ISurrogateSelector (yang memetakan ke properti surrogateSelector). Ini adalah mekanisme pengganti warisan.

  • Konstruktor menerima parameter yang disebut assemblyFormat dari FormatterAssemblyStyle yang memetakan ke properti AssemblyFormat. Seperti yang dibahas sebelumnya, ini dapat digunakan untuk meningkatkan kemampuan pengelolaan versi dari serializer. Ini identik dengan FormatterAssemblyStyle mekanisme dalam serialisasi biner atau SOAP.

  • Konstruktor menerima parameter StreamingContext yang disebut context dan memetakan ke properti Context. Anda dapat menggunakan ini untuk meneruskan informasi ke jenis yang sedang diserialkan. Penggunaan ini identik dengan mekanisme StreamingContext yang digunakan di kelas System.Runtime.Serialization lain.

  • Metode Serialize dan Deserialize adalah alias untuk WriteObject metode dan ReadObject . Ini ada untuk menyediakan model pemrograman yang lebih konsisten dengan serialisasi biner atau SOAP.

Untuk informasi selengkapnya tentang fitur-fitur ini, lihat Serialisasi Biner.

Format XML yang NetDataContractSerializer digunakan dan DataContractSerializer biasanya tidak kompatibel. Artinya, berusaha melakukan serialisasi dengan salah satu serializer ini dan deserialisasi dengan yang lain bukanlah skenario yang didukung.

Perhatikan juga bahwa NetDataContractSerializer tidak menghasilkan jenis .NET Framework lengkap dan nama rakitan untuk setiap simpul dalam grafik objek. Menampilkan informasi itu hanya ketika ambigu. Artinya, ia menghasilkan keluaran pada tingkat objek akar dan untuk semua kasus polimorfik.

Lihat juga