.NET’te Serileştirme & Ters Serileştirme (Serialization & Deserialization)

Serialization(serileştirme), bir nesnenin o anki durumunu(içeriğini) belli bir formata dönüştürüp geçici veya kalıcı bir kaynak üzerinde depolama işlemidir. Bu kaynak bir disk olabildiği gibi hafıza veya network üzerindeki bir akım da olabilir. .NET Framewok’ün birçok sınıfında gizli olarak kullanılan bu işlem daha çok .NET Framework’ün en önemli bileşenlerinden olan Remoting mimarisinde etkilidir. Bu mimaride veriler, serileştirilerek farklı uygulamalar arasında taşınır. Serileştirilmiş veriyi geri elde etme yani orijinal nesne haline çevirme işlemini de deserialization(ters-serileştirme) denilir.
Bir sınıfın serileştirme işlemini desteklemesi için Serializable özniteliğini uygulaması olması gerekir. Ayrıca sınıfı, ISerializable arabiriminden türeterek sınıfının serileştirilmesiyle ilgili daha detaylı ayarlar yapılabilir. DataSet nesnesini WriteXml() metodunu kullanarak güncel içeriğini bir XML belgesine kaydedebiliyor olmamız veya ReadXml() metodu aracılığıyla XML içeriği DataSet içerisine aktarabiliyor olmamızın temelinde DataSet nesnesinin ISerializable ve IXmlSerializable arabirimlerinden türemiş olması yatar.
.NET Framework, 3 tür serileştirme yöntemi sunar:

    İkili Serileştirme (Binary Serialization)
    XML (XML Serialization)
    SOAP Serileştirme (SOAP Serialization)

İkili serileştirme, nesnenin son durumunu bit bit serileştirip bu bilgiyi, diskte bir dosyaya kaydetmek veya .NET Remoting mimarisini kullanarak birbirinden bağımsız uygulamalar arasında taşımak için tercih edilir. Diğer serileştirme yöntemlerinden daha hızlıdır ve daha az bir çıktı üretir. İkili serileştirme işleminden < ı>System.Runtime.Serialization.Formatters.Binary ad alanı altında bulunan BinaryFormatter sınıfı sorumludur. Bu sınıfın, Serialize() metodu kullanılarak nesneler ikili formata dönüştürülür aynı şekilde Deserialize() metodu kullanılarak ikili içerik uygun nesne yapısına dönüştürülür.
Aşağıdaki örnekte basit bir sınıf oluşturulmuş ve bu sınıf tipindeki bir nesnenin ikili formata dönüştürülmesi gösterilmiştir.


Bu durumda Musteri nesnesi ikili tabanda serileştirilir ve oluşan çıktı C:\Musteri.bin dosyasına yazdılır. Bu dosyadaki içerik ikili formatta olduğu için okunabilir bir yapıda değildir.
Bu dosyayı ters serileştirme işleminden geçirip dosyadaki verileri gerçek bir Musteri nesnesine dönüştürelim. Bunun için BinaryFormatter sınıfının Deserialize() metodu kullanılır.
'Serileştirilecek müşteri nesnesini oluşturalım
Dim oM As Musteri = Nothing

'Nesneyi kendisinden deserialize edeceğimiz stream'i tanımlayalım
Dim oFs As New FileStream("C:\Musteri.bin", FileMode.Open)

'Binary deserialize yapacak nesneyi oluşturalım
Dim oBf As New BinaryFormatter()
'Stream içindeki içeriği oM nesnesine deserialize edelim.
oM = oBf.Deserialize(oFs)

Console.Write(oM.MusteriId & ", " & oM.AdSoyad & ", " & oM.DogumTarih)
//Serileştirilecek müşteri nesnesini oluşturalım
Musteri oM = null;

//Nesneyi kendisinden deserialize edeceğimiz stream'i tanımlayalım
FileStream oFs = new FileStream(@"C:\Musteri.bin", FileMode.Open);

//Binary deserialize yapacak nesneyi oluşturalım
BinaryFormatter oBf = new BinaryFormatter();
//Stream içindeki içeriği oM nesnesine deserialize edelim.
oM = (Musteri)oBf.Deserialize(oFs);

Console.Write(oM.MusteriId + ", "+ oM.AdSoyad +", "+ oM.DogumTarih);

1, Ali Çetin, 28.02.1978 00:00:00
İkili serileştirmede sınıf içerisinde serileştirme işlemine dahil edilmesi istenilmeyen üyeler, NonSerialized özniteliğiyle belirtilir.
ADO.NET’in en önemli bileşeni olan DataSet nesnesinin, verileri XML formatında sakladığını biliyoruz. Özellikle farklı konumlardaki uygulamalar arasında yüksek boyutlu DataSet nesnelerinin taşınması veri iletişim süresini uzatabilmektedir. DataSet nesnesi ikili serileştirme işleminden geçirilse bile temelde veriyi yine XML formatında sakladığı için veri boyutunda ciddi bir küçülme olmamaktadır. Bu sorunu aşmak için ADO.NET 2.0 ile birlikte DataSet sınıfına RemotingFormat isimli property eklendi. Bu property, SerializationFormat.Binary veya SerializationFormat.Xml değerlerinden birini alır. Böylece Binary seçeneği seçilerek gerçek anlamdan ikili serileştirme işlemi yapılmış olur.
XML serileştirme, uygulamadaki bir nesnenin güncel durum bilgisini XML formatına dönüştürme amaçlı kullanılır. XML, açık standart bir format olduğu ve işlenmesi kolay olduğu için genellikle farklı uygulamalar arasında veri paylaşımında tercih edilir. Örneğin uygulamadaki bir DataSet nesnesini serileştirip Internet üzerinden başka bir uygulamaya gönderebiliriz. Karşıdaki uygulama aldığı XML içeriği ters serileştirme işleminden geçirip DataSet nesnesinin son durumunu elde etmiş olur. XML serileştirmenin çıktısı, doğası gereği ikili çıktıya göre daha anlaşılır bir formata sahiptir. XML serileştirmenin bazı kısıtlamaları bulunur:

    Sadece public nitelikli property ve field türündeki üyeler serileştirilebilir. Method, indexer, read-only property ve private nitelikli üyeler serileştirilemez. Read-only collection türündeki üyeler serileştirilebilir.
    Sadece verinin kendisini serileştirir veritipleri bilgilerini serileştirmez. Bu yüzden ters serileştirme işleminde dönüştürülen nesnenin aynı tipte olması garantilenmez.

XML tabanlı serileştirmede rol oynayan sınıflar < ı>System.Xml.Serialization kütüphanesi altında bulunur. XML tabanlı serileştirme işleminden sorumlu olan sınıf XmlSerializer sınıfıdır. Bu sınıfın Serialize() metodu, nesnenin güncel içeriğini XML formatına dönüştürür, Deserialize() metodu, Serialize() metodunun ters işlemini gerçekleştirir yani XML verisinden uygun nesneyi oluşturur. Bu sınıfın diğer önemli üyesi olan CanDeserialize() metodu, XML verisinin ters serileştirme işlemi için uygun olup olmadığını denetler.
XML serileştirme işleminde, serileştirilecek nesnenin tipi, XmlSerializer sınıfının yapıcı metoduna parametre olarak geçilir.

'Serileştirilecek müşteri nesnesini oluşturalım
Dim oM As New Musteri()
oM.MusteriId = 1
oM.AdSoyad = "Ali Çetin"
oM.DogumTarih = New DateTime(1978, 2, 28)

'Serileştirmenin yapılacağı bir akım oluşturalım.
'Burada örnek olarak file stream'ı kullanacağız.
Dim oFs As New FileStream("C:\Musteri.xml", FileMode.Create)

'XML serileştirme yapacak nesneyi oluşturalım
'XmlSerializer'ın yapıcı metoduna Musteri sınıfının tipi gönderilir
Dim oXs As New XmlSerializer(GetType(Musteri))

oXs.Serialize(oFs, oM)
//Serileştirilecek müşteri nesnesini oluşturalım
Musteri oM = new Musteri();
oM.MusteriId = 1;
oM.AdSoyad = "Ali Çetin";
oM.DogumTarih = new DateTime(1978, 02, 28);

//Serileştirmenin yapılacağı bir akım oluşturalım.
//Burada örnek olarak file stream'ı kullanacağız.
FileStream oFs = new FileStream(@"C:\Musteri.xml", FileMode.Create);

//XML serileştirme yapacak nesneyi oluşturalım
//XmlSerializer'ın yapıcı metoduna Musteri sınıfının tipi gönderilir
XmlSerializer oXs = new XmlSerializer(typeof(Musteri));

oXs.Serialize(oFs, oM);

Bu işlemden sonra Musteri nesnesinin o anki durumu XML formatında diske yazılır.

Görüldüğü gibi belge içerisinde alanların veri tipleriyle ilgili tanımlama bulumamaktadır.
Şimdi bu belgedeki verileri sözkonusu Musteri sınıfına uygun bir nesneye geri yükleme yapalım.

'Yeni bir Musteri nesnesi oluşturalım
Dim oM As Musteri = Nothing

'Deserialization işleminde kullanılacak serializer nesnesi
Dim oXs As New XmlSerializer(GetType(Musteri))

Dim oXr As XmlReader = New XmlTextReader("C:\Musteri.xml")

'XML verisinin Deserialize durumunu denetleyelim
If oXs.CanDeserialize(oXr) Then
    'XML verisini deserialize edelim
    oM = oXs.Deserialize(oXr)
    Console.Write(oM.MusteriId & ", " & oM.AdSoyad & ", " & oM.DogumTarih)
End If
//Yeni bir Musteri nesnesi oluşturalım
Musteri oM = null;

//Deserialization işleminde kullanılacak serializer nesnesi
XmlSerializer oXs = new XmlSerializer(typeof(Musteri));

XmlReader oXr = new XmlTextReader(@"C:\Musteri.xml");

//XML verisinin Deserialize durumunu denetleyelim
if (oXs.CanDeserialize(oXr))
{
    // XML verisini deserialize edelim
    oM = (Musteri)oXs.Deserialize(oXr);
    Console.Write(oM.MusteriId + ", " + oM.AdSoyad + ", " + oM.DogumTarih);
}

1, Ali Çetin, 28.02.1978 00:00:00
< ı>System.Xml.Serialization ad alanı, XML formatında serileştirilecek nesneyle ilgili detaylı ayarlama yapmak için çeşitli öznitelikler içerir. Örneğin nesneye ait bir özelliği, XML belgesinde öznitelik olarak tanımlamak için XmlAttribute niteliği, serileştirme işlemine dahil edilmeyecek alanlar için XmlIgnore niteliği, alanın XML belgesindeki elemen yapısını düzenlemek için XmlElement niteliği kullanılır. Musteri sınıfını aşağıdaki gibi düzenleyelim.

Public Class Musteri
    

Bu durumda örnekte kullandığımız nesnenin XML çıktısı şu şekilde olacaktır.

<u><b>SOAP serileştirme,</b></u> XML serileştirme işleminin bir türü olup SOAP formatında serileştirme yapmak için kullanılır. Basit nesne erişim prokolü olarak tanımlanan SOAP(Simple Object Access Protocol), uygulamalar arasında HTTP üzerinden veri iletimini sağlamak amacıyla geliştirilmiş XML tabanlı bir iletişim protokolüdür. Bu protokol, dağıtık uygulamalarda ve web servislerinin haberleşmesinde kullanılılır.
.NET Framework'te nasıl ki ikili serileştirme, BinaryFormatter isimli formatter nesnesi tarafından gerçekleştiriliyorsa SOAP serileştirme de SoapFormatter isimli formatter nesnesi tarafından gerçekleştirilir. SoapFormatter sınıfı, < ı>System.Runtime.Serialization.Formatters.Soap.dll kütüphanesi altında bulunmaktadır. SOAP serileştirme için projemize bu kütüphaneyi referans olarak eklemeyi unutmamalıyız. SoapFormatter sınıfının da serileştirme işlemini yapan <b>Serialize()</b> ve ters serileştirme işlemini yapan <b>Deserialize()</b> metodu bulunur.


Bu şekilde serileştirilmiş nesne, aşağıdaki içeriğe dönüştürülür.

Serileştirilmiş SOAP formatındaki bu veriyi uygulamadaki Musteri nesnesine dönüştürelim.
Dim oM As Musteri = Nothing

Dim oFs As New FileStream("C:\Musteri.xml", FileMode.Open)
Dim oSf As New SoapFormatter()

'SOAP verisini deserialize edelim
oM = oSf.Deserialize(oFs)
Console.Write(oM.MusteriId & ", " & oM.AdSoyad & ", " & oM.DogumTarih)
Musteri oM = null;

FileStream oFs = new FileStream(@"C:\Musteri.xml", FileMode.Open);
SoapFormatter oSf = new SoapFormatter();

// SOAP verisini deserialize edelim
oM = (Musteri)oSf.Deserialize(oFs);
Console.Write(oM.MusteriId + ", " + oM.AdSoyad + ", " + oM.DogumTarih);

1, Ali Çetin, 28.02.1978 00:00:00
Serileştirmeyle ilgili olarak yine bizim tarafımızdan yazılmış başka bir nesneyle ilişkili bir nesneyi kullanalım. Musteri sınıfına AdresBilgi isimli başka bir sınıfın türünden olan Adres isimli bir property ekleyelim.


Bu verilere göre XML ve SOAP serileştirme işleminde bulunalım.
'Akım nesnesi
Dim oFs As New FileStream("C:\Musteri.xml", FileMode.Create)

Dim oXs As New XmlSerializer(GetType(Musteri))

oXs.Serialize(oFs, oM)
//Akım nesnesi
FileStream oFs = new FileStream(@"C:\Musteri.xml", FileMode.Create);

XmlSerializer oXs = new XmlSerializer(typeof(Musteri));

oXs.Serialize(oFs, oM);

Adres düğümü, Musteri düğümünün bir alt elementi olarak tanımlanmıştır. SOAP tabanlı serileştirmeye bakalım.

'Akım nesnesi
Dim oFs As New FileStream("C:\Musteri.xml", FileMode.Create)

Dim oSf As New SoapFormatter()

oSf.Serialize(oFs, oM)
//Akım nesnesi
FileStream oFs = new FileStream(@"C:\Musteri.xml", FileMode.Create);

SoapFormatter oSf = new SoapFormatter();

oSf.Serialize(oFs, oM);

Sonuçta grüldüğü gibi Adres alanı için ayrı bir veri tipi tanımlaması yapılmış ve Adres alanından o veri tipine referans verilmiştir.

.NET’te Serileştirme & Ters Serileştirme (Serialization & Deserialization)” üzerine bir düşünce

  1. Mustafa Demir

    Cok super bir anlatim olmus, her ne kadar oturup kodlamaya baslamadan iyice ogrenilemeyecegi icin, genel olarak anlamak icin cok guzel. Remoting uygulamalari gelistiriyorsaniz mutlaka ogrenilmasi gereken bir konu. Kitaplarinizi da ayrica siparis ettim, dort gozle bekliyorum derinlemesine ogrenebilmek icin.

    Cevapla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.