Serilizasyon

Yazar: Koray Kırdinli
Kategori: C#.NET & VB.NET
Eklenme Tarihi: 14.7.2010 06:25:29



Bir çok uygulama bir nesne içerisinde veriyi saklamaya veya transfer etmeye ihtiyaç duyar. Bunu .NET içerisinde yapmanın en kolay yolu serilizasyondur.

Bir çok uygulama bir nesne içerisinde veriyi saklamaya veya transfer etmeye ihtiyaç duyar. Bunu .NET içerisinde yapmanın en kolay yolu serilizasyondur. 3 tip serileştirme tekniği vardır. Bunlar Binary, SOAP ve XML Serilization.
Bir uygulamada veriyi memory’de serileştirip saklamak , network üzerinden transfer etmek ve tekrardan nesneyi oluşturmak serilizasyon ve deserilizasyon ile mümkündür.
Serilizasyon bir nesneyi alıp bir dizi lineer byte dizisine çevirme işlemidir diyebiliriz.
Serilizasyon sınıfları System.Runtime.Serialization namespace’i altındadır.

Serilizasyon nerede işimize yarar:
Eğer bir nesneyi bir dosyaya serileştirme yapmadan yazıp daha sonra okumak istersek bu sefer nesnenin property’lerini manuel olarak set etmemiz gerekecek fakat serilizasyon işleminde nesneyi olduğu gibi geri alabilmek mümkün.
Diğer bir örnek: Bir nesneyi farklı bir bilgisayarda çalışan bir programa network üzerinden bu nesneyi gönderebilir , remoote uygulamada bu nesneyi deserilize edip işlemlerini yapabilir.
Windowsta bir nesneyi clipboard’a kopyaladığımızda,web servislerinde,remoting yaparken serilizasyon yapmaktadır.

Basit olarak bir binary serileştirme işleminin adımlarını yazacak olursak.
1- Stream nesnesi oluşturulur ( File veya MemoryStream)
2- BinaryFormatter nesnesi oluşturulur
3- Formatter’ın serialize metodu çağrılır ve stream kapatılır.

string data = "Koray Kırdinli";

FileStream fs = new FileStream("SerializesString.Data", FileMode.OpenOrCreate);

BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(fs, data);
fs.Close();

Fakat yukarıdaki işlemde serilizasyon yapmak çok efektif değil düz bir şekilde dosyaya da yazabilirdik. Serilizasyon daha kompleks işlemlerde asıl faydasını göstermekte yani nesneleri. Örneğin bir teks değilde DateTime’ı serilize etmek örnek olarak verilebilir.

Desirilazasyon işlemi ise serilizasyonun tam tersidir. Aşağıdaki kod yardımı ile serilize ettiğimiz bir nesneyi geri almamız mümkün.

FileStream fs = new FileStream("SerializesString.Data", FileMode.Open);

BinaryFormatter bf = new BinaryFormatter();

string data = (string)bf.Deserialize(fs);

fs.Close();


Kendi yazdığımız bir sınıfı da Serilizable niteliği sayesinde serilize edilebilir hale getirebiliriz. Ayrıca serilizasyon işlemi System.Security.Permissions namespace’i altındaki SecurityPermission niteliğine ihtiyaç duyar. Default olarak bu policy’ye internetten indirilen veya intranet bir kod parçasında izin verilmez fakat lokal makinada izin verilir. Bunun sebebi ise gizli veriyi koruma altına almaktır.

[Serializable]

public class ShoppingCartItem : IDeserializationCallback

{

public int ProductId;

public decimal Price;

public int Quantity;

[NonSerialized] public decimal Total; // Bu değer dinamik hesaplandığı için

//ve verinin boytunu küçültmek için serilize etmiyoruz.

[OptionalField] public bool Taxable;

//Eğer bir field'a OptionalField niteliğini eklersek bu field daha önce serilize

//edilmiş veride olmasa bile uygulama hata fırlatmaz. Versiyon uyumluluğu için kullanılabilir.

#region IDeserializationCallback Members

//Bu sınıfın nesnesi deserilize olurken IDeserializationCallback interface'ini

//implement edip OnDeserialization eventi içerisinde hesaplatma işlemini yapıyoruz.

public void OnDeserialization(object sender)

{

Total = Price * Quantity;

}

#endregion

}


.NET Framework serilize edilmiş veriyi formatlamak için System.Runtime.Serialization namespace’i altında 2 formatlayıcı barındırıyor. İkisi de IRemotingFormatter interface’ini implemente eder.
BinaryFormatter : System.Runtime.Serialization.Formatters.Binary namespace’i altındadır. Eğer serilize eden ve deserilize eden uygulama .NET ile yazılmışsa kullanılmalıdır.
SoapFormatter : System.Runtime.Serialization.Formatters.Soap namespace’i altındadır.Eğer deserilize edecek uygulama .NET ile yazılmamışsa kullanmak mantıklıdır. Ayrıca Firewall’lardan daha rahat geçer. Yani network uygulamalarında daha başarılıdır.Kullanmak için System.Runtime.Serialization.Formatters.Soap.dll ‘i uygulamaya referans vermek gereklidir. Binary Formatter ile serileştirilmiş veriyi okuması daha zor iken Soap ile serileştirilmiş veri xml tabanlı daha düzgün bir şekilde okunabilir.

ShoppingCartItem entity = new ShoppingCartItem(1, 100m, 10, 1000);

FileStream fs = new FileStream("SerializeSoap.Data", FileMode.OpenOrCreate);

SoapFormatter bf = new SoapFormatter();

bf.Serialize(fs,entity);

fs.Close();

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<SOAP-ENV:Body>

<a1:ShoppingCartItem id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ileriWindowsForms/ileriWindowsForms%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">

<ProductId>1</ProductId>

<Price>100</Price>

<Quantity>10</Quantity>

<Taxable>false</Taxable>

</a1:ShoppingCartItem>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>


ShoppingCartItem entity = new ShoppingCartItem();

FileStream fs = new FileStream("SerializeSoap.Data", FileMode.Open);

SoapFormatter bf = new SoapFormatter();

entity = (ShoppingCartItem)bf.Deserialize(fs);

fs.Close();

MessageBox.Show(

String.Format("Pid:{0},Price{1},Quantity={2},TOTAL={3}",

entity.ProductId,entity.Price,entity.Quantity,entity.Total));


XML serileştirme veriyi farklı sistemlerin veri alışverişini sağlayabilmek amacıyla oluşturulmuş XML yapısında saklamaktadır..NET içerisinde XML dökümanına yazma ve okuma için bir çok sınıf mevcuttur. System.Xml.Serialization namespace’i altında serileştirme sınıflarını bulabilirsiniz.
Peki ne zaman Xml serileştirme kullanmalıyız : Eğer deserilize edecek uygulama .NET değil ve nesne olduğu gibi serileştirilecek ise XML serileştirme kullanılabilir. Bu yöntem text tabanlı olduğu için bütün işletim sistemlerinde ve uygulama ortamlarında kolayca okunabilir. Ayrıca bir notepad gibi basit bir araçla bile kolayca okunabilir. Özellikle uygulamaları customize etmekte oldukça kullanışlıdırlar.

FileStream fs = new FileStream("SerializeDate.xml", FileMode.OpenOrCreate);

XmlSerializer xs = new XmlSerializer(typeof(DateTime));

xs.Serialize(fs, DateTime.Now);

fs.Close();

MessageBox.Show(DateTime.Now.ToLongTimeString());

FileStream fs = new FileStream("SerializeDate.xml", FileMode.Open);

XmlSerializer xs = new XmlSerializer(typeof(DateTime));

DateTime date = (DateTime)xs.Deserialize(fs);

fs.Close();

MessageBox.Show(date.ToLongTimeString());

Bir sınıfı aşağıdaki şekilde Xml serilizasyona uygun hale getirebiliriz.

[XmlRoot("Cart")]

public class CartItem

{

[XmlAttribute] public Int32 productId;

public decimal price;

public Int32 quantity;

[XmlIgnore] public decimal total;

}


Eğer iki farklı uygulama xml dosyaları paylaşacaklar ise developer’lar xml standartlarını ortak olarak belirleyebilmek için xml schema’lardan yararlanırlar.Xml schema xml dökümanının yapısını belirler.Xml schemaları oluşturmak için xsd.exe gibi bir araçtan faydalanılabilir.Veya standart olarak .NET içerisindeki XmlReader ve XmlWriter sınıflarından yararlanılabilir.

Bir dataseti ister yukarda anlattığımız yöntem ile ya da myDataSet.WriteXml("DataSet.xml"); metodu ile direk olarak serilize edebiliriz.

Custom Serilization : Bir sınıfı ISerilizable sınıfının GetObjectData metodunu override ederek default serilizasyonu kullanmadan custom bir serilizasyon yapabiliriz. Bu bir nesnenin geçersiz bir elemanı olduğunda işimize yarayabilir.
GetObjectData metonunda parametre olan SerilizationInfo nesnesi içerisine elemanları doldurmak gereklidir.Bu elemana name/value çifti olarak elemanlar yerleştirilir.


[SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)]

public void GetObjectData(SerializationInfo info, StreamingContext context)

{

info.AddValue("Product Id ", productId);

info.AddValue("Price",price);

info.AddValue("Quantity", quantity);

}

Serilizasyon işlemlerinde istediğimiz aşamada veriye müdahale etme şansımız bulunmaktadır. Bunu xml nitelikleri ile yapabiliyoruz.
[OnSerializing] : Sınıf içerisine bir metoda bu tagı eklersek o metod nesneyi serilize ederken çalışır.

[OnSerialized] : Serilizasyon işlemi bittikten sonra çalışır.

[OnDesilizating] : Desilize işlemi nesne deserilize işlemi yapılırken çalışır.

IDesirilizationCallback,OnDesilization()
[OnDesirialized] : Deserilize işlemi bitince çalışır.


[Serializable]

public class Customer

{

public Int32 productId;

public decimal price;

public Int32 quantity;

public decimal total;
//Bu metodalar parametre olarak StreamingContext almak ve void return etmek //zorundadırlar.

[OnSerializing]

void CalculateTotal(StreamingContext sc)

{

total = price * quantity;

}

[OnDeserialized]

void CheckTotal(StreamingContext sc)

{

if (total == 0) CalculateTotal(sc);

}

}


Koray Kırdinli

1983 Uşak doğumlu. 2006 yılında Eskişehir Osmangazi Üniversitesi Bilgisayar Mühendisliği bölümünden mezun oldu. O yıldan itibaren C#,ASP.NET,Sql ve Oracle teknolojileri ile windows ve web tabanlı projeler geliştirmektedir.
Şu an istanbulda özel bir bankada Yazılım Geliştirme Uzmanı olarak görev yapmaktadır
(Detay için : http://koraykirdinli.blogcu.com adresini ziyaret edebilirsiniz  )
Bu makaleye ilk yorum yapan siz olun.

Yorumunuz