Son durumlarını korumak istediğimiz nesnelerin düzenli ve belli bir biçimde her hangi bir veri saklama ortamında saklanması işlemine serilestirme (serialization), serileştirilmiş bilgilerin saklama ortamından okunup nesnenin yeniden oluşturulması işlemine ters-serileştirme (deserialization) denir. .Net kütüphanesi bu işlemi kolayca yapmamız için bize iki farklı yöntem sunmuştur.
- İkili (binary) serileştirme
- XML ya da SOAP serileştirme
XML dosyaları metin tabanlıdır. Basit bir metin editörü ile açılıp değiştirilebilirler. Düzenlemesi kolaydır ve bir çok program bu tür dosyaları kullanabilir.
Her ne kadar XML biçimi son zamanlarda popülerleşse de, bence, ikili saklama her zaman tahtını koruyacaktır. Çünkü, ikili dosyaları düzenlemek XML dosyalarını düzenlemek kadar kolay değildir. İmkasız olmasa da ikili dosyalardan bilgi çalmak daha zordur. İkil dosyalar XML'e göre çok daha az yer kaplarlar ve ağ iletimi için daha uygundurlar.
İkili Serileştirme
İkili serileştirme için, System.Runtime.Serialization.Formatters.Binary ad uzayı altında BinaryFormatter nesnesı kullanılır. BinaryFormatter'ın nasıl kullanıldığını basit bir örnekle açıklayacağım. Bu orneğin kodlarını buradan indirebilirsiniz: Serilestirme.rar (6,14 kb)...
Bu örnek için, Ornek ve OrnekCollection isimli iki sınıf yazdım. Kodları aşağıda:
[Serializable]
class Ornek
{
public string Ad { get; set; }
public string SoyAd { get; set; }
public string Aciklama { get; set; }
}
[Serializable]
class OrnekCollection : List<Ornek> { }
Gördüğünüz gibi sınıflar çok basit. Ornek sınıfının yalnızca üç adet özelliği var. OrnekCollection sınıfının ise hiç kodu yok yalnızca System.Collections.Generic altındaki List sınıfını kalıtmış. Fark edebileceğiniz gibi her iki sınıf da Serializable özniteliğiyle işaretlenmiş. Bu, bu kodda ki en önemli nokta, çünkü bir nesneyi serileştirebilmeniz için; nesnenin Serializable özniteliği ile işaretlenmesi gereklidir. Eğer nesne bununla işaretlenmemişse SerializationException fırlatılır.
Örnekte bu iki sınıf dışında bir de Program sınıfı var. Örnek kodları bu sınıfın içinde. Şimdi bu sınıfı inceyelim.
private static OrnekCollection KolleksiyonuOlustur(int elemanSayisi)
{
OrnekCollection ornekCollection;
Console.WriteLine(elemanSayisi.ToString() + " elemanli dizi olusturuluyor...");
for (ornekCollection = new OrnekCollection(); elemanSayisi > 0; elemanSayisi--)
ornekCollection.Add(new Ornek()
{
Ad = "Merve (" + elemanSayisi.ToString() + ")",
SoyAd = "evrem",
Aciklama = "Bu, olusturdugumuz " + (10 - elemanSayisi).ToString() + ". elemandir"
});
Console.WriteLine(ornekCollection.Count.ToString() + " elemanli dizi olusturuldu.");
return ornekCollection;
}
Yukarıda kodları verilen KolleksiyonuOlustur fonksiyonu parametre aldığı elemanSayisi kadar eleman oluşturup geri döndürür.
private static void DiziyiListele(OrnekCollection ornekCollection)
{
Console.WriteLine(ornekCollection.Count.ToString() + " elemanli dizi listeleniyor...\n");
int eleman = 0;
string s = "\t{0}. eleman\n\t\tAdi: {1}\n\t\tSoyadi: {2}\n\t\tAciklama: {3}";
foreach (Ornek i in ornekCollection)
Console.WriteLine(
string.Format(s, ++eleman, i.Ad, i.SoyAd, i.Aciklama)
);
Console.WriteLine("\n" + ornekCollection.Count.ToString() + " elemanli dizi listelendi.\n");
}
Yukarıda ki fonksiyon ise dizinin elemanlarını ekrana yazdırır.
private static void Serilestir(string file, OrnekCollection o)
{
Console.WriteLine(o.Count.ToString() + " elemanli dizi serilestiriliyor...");
BinaryFormatter binaryFormatter;
binaryFormatter = new BinaryFormatter();
if (File.Exists(file))
File.Delete(file);
FileStream fileStream = new FileStream(file, FileMode.CreateNew);
binaryFormatter.Serialize(fileStream, o);
fileStream.Close();
Console.WriteLine(o.Count.ToString() + " elemanli dizi serilestirildi...");
}
Tüm örneğin iki can alıcı noktasından birincisi, yukarıda ki kodda altı çizili olan kısım. BinaryFormatter nesnesinin, Serialize fonsiyonu bir nesneyi serileştirir. Bu fonksiyon iki parametre alır, birinci parametresi serileştirilmiş bilginin yazılacağı Stream, ikincisi ise serileştirilecek nesnedir. Bu fonksiyonun çalıştırılması sırasında üç farklı istisnai durum oluşabilir, bunlar:
- System.ArgumentNullException
Parametre olarak verilen iki değerden birisi null ise, bu istisnai durum fırlatılırç
- System.Runtime.Serialization.SerializationException
Serileştirme sırasında, serileştirme ile ilgili bir hata oluşursa, bu istisnai durum fırtlatılır. Bu istisnai durum genelde, ikinci parametrede belirtilen nesnenin Serializable özniteği ile işaretlenmemiş olması durumunda fırlatılır.
- System.Security.SecurityException
Serileştirme istiğini yapan uyguluma yeterli güvenlik seviyesinde değilse bu istisnai durum fırlatılır.
private static OrnekCollection TersSerilestir(string file)
{
Console.WriteLine("Nesne ters-serilestiriliyor...");
BinaryFormatter binaryFormatter = new BinaryFormatter();
FileStream fileStream = new FileStream(file, FileMode.Open);
OrnekCollection ornekCollection = (OrnekCollection)binaryFormatter.Deserialize(fileStream);
fileStream.Close();
Console.WriteLine(ornekCollection.Count.ToString() + " elemanli dizi ters-serilestirildi...");
return ornekCollection;
}
Tüm örneğin en can alıcı ikinci kısmı ise, yukarıdaki kodda ki altı çizili kısım. BinaryFormatter nesnesinin Deserialize fonksiyonu bir Stream üzerinden ters-serileştirme işlemi yapar. Bu fonksiyon parametre olarak bir Stream nesnesi alır. Parametre olarak aldığı akımdan ikil okuma yapar ve nesneyi yeniden oluşturur. Fonksiyonun geri dönüş değeri object'tir. Bu nedenle, oluşturulan nesneyi bir yere atamadan önce tür dönüşümü yapmalıyız.
Bu fonksıyonun da çalışması esnasında üç adet istisnai durum oluşabilir. Bu durumlar, Serialize fonksiyonuyla aynı olmakla birlikte; SerializationException, parametre olarak belirtilen akımın Seek işlemini desteklememesi, uzunluğunun 0 olması ya da belirtilen akımın bir Serileştirilmiş bir nesne olmaması durumunda oluşur.
XML Serileştirme
XML serileştirmede de neredeyse aynı kodları kullanıyoruz. XML serileştirmenin bir kaç fark var, bunlar:
- System.Runtime.Serialization.Formatters.Binary.BinaryFormatter yerine System.Xml.Serialization.XmlSerializer kullanıyoruz.
- Nesneyi boş yaratıcı metodla oluşturamıyoruz. Nesneyi oluşturmak için, XmlSerializer xmlSerializer = new XmlSerializer(typeof(OrnekCollection)); gibi bir kod kullanıyoruz.
Bu yöntemin örneği için, diğer örnekteki; TersSerilestir ve Serilestir fonksiyonlarında ilgili yerleri değiştirmeniz yeterlidir, ya da kısaca buradan indirebilirsiniz: SerilestirmeXML.rar (6,33 kb)
Xml Serileştirmede, akımdakı verinin serileştilip serileştiremeyeceğini, nesnenin CanDeserialize fonksiyonu ile öğrenebiliriz. Bu fonksiyon System.Xml.XmlReader türünden bir parametre alır.
private static OrnekCollection TersSerilestir(string file)
{
Console.WriteLine("Nesne ters-serilestiriliyor...");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(OrnekCollection));
FileStream fileStream = new FileStream(file, FileMode.Open);
System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(fileStream);
OrnekCollection ornekCollection;
if(xmlSerializer.CanDeserialize(xmlReader))
ornekCollection = (OrnekCollection)xmlSerializer.Deserialize(xmlReader);
else
{
Console.WriteLine("Nesne ters-serilestirilemez. Gecersiz dosya.");
Console.ReadKey(false);
return null;
}
fileStream.Close();
Console.WriteLine(ornekCollection.Count.ToString() + " elemanli dizi ters-serilestirildi...");
return ornekCollection;
}
Yukarıda ki kodu örnekte ki ile değiştirirseniz, hata oluşma ihtimalini biraz daha azaltabilirsiniz.
Sonunda bu makaleyi/yazıyı da bitirdim. İnşallah size bir yararı dokumuştur. Bir sorunuz varsa bana her zaman eposta atabilirsiniz ve son olarak bir defa daha örnekleri vereyim:
- İkili serileştirme örneği: Serilestirme.rar (6,14 kb)
- XML serileştirme örneği: SerilestirmeXML.rar (6,33 kb)