Serialization (Serileştirme) & Deserialization
Bu makalemizde Serialization (Serileştirme) & Deserialization işlemlerini ele alacağız. .Net Framework içinde hali hazırda bize sunulan iki adet yapı mevcuttur. [ BinarySerialize ve XmlSerialize ] Ek olarak kullanabileceğimiz JsonSerialize yapısı da serialize işlemlerinde özellikle servis tabanlı veya web projelerinde oldukça fazla kullanılmaktadır.
-
Serialize & Deserialize İşlemi Nedir ?
- Serialization işlemi en basit anlamıyla nesnenin o anki durumunun belirlenen yöntem doğrultusunda saklamasıdır. Bellek (Memory) , Dosya (File) , veri tabanı (Database) bazlı saklama işlemleri yapılabilir. İstenildiğinde serialize edilmiş obje DeSerialize işlemi ile birlikte tekrar kullanıma uygun hale getirilebilir. Serialization işlemleri genel olarak dosya gönderme, veritabanı üzerine dosya kaydetme, nesne üzerinden veri taşıma gibi durumlarda kullanılmaktadır.
Binary Serialization
BinarySerialization ‘ın en önemli özelliklerinden biri tip güvenli olmasıdır. Serialize edeceğiniz nesne deserialize işleminde aynı şekilde size dönecektir. BnarySerialization işleminin avantajları olduğu gibi dezavantajları da vardır.Şimdi bu durumları anlayabilmek için oluşturacağımız senaryoyu ilerletelim. Program içinde kulandığımız data veya nesne’yi aktaracağımızı varsayalım. BilisimIOData adında bir sınıfımız olsun. Sınıfı serialize edip gönderdiğimizde deserialize edilen ordamda BilisimIOData sınıfının olması zorunluluğu vardır. Öte yandan Binary mantık olarak elindeki objeyi veya datayı ondalik sisteme çevirip işlemektedir. Bu durum bize BinarySerialization işleminin Human Readable (bizim anlayabileceğimiz şekilde okunabilir veri) olmadığını göstermektedir ve düzenlenebilir bir data değildir. Binary olarak serialize edilmiş bir dosyayı açıp içinde bir değişiklik yapılırsa dosya bozulacaktır ve deserialize edilemeyecektir. BinarySerialization da her platformun nesne yapısı farklı olduğundan CrossPlatform ( Farklı ortam ) desteği yoktur. Şimdi örneğimize geçelim. Projemiz içinde oluşturacağımız sınıf’ ı Binary serialize ve deserialize işlemine tabi tutalım.
Yeni bir ConsoleApplication oluşturuyoruz. Oluşturduğumuz proje içinde Serialization&Deserialization işleminde kullanılmak üzere Author.cs sınıfını ekliyoruz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
namespace bilisim.io { [Serializable] public class Author { public string Name ; public string SurName ; public string FullName { get { return string.Concat(Name, SurName); } } } |
Sınıfları serialize edebilmek için [Serializable] attribute ‘ unu örnekte olduğu gibi eklememiz gerekmektedir. Bu eklemeyi yapmadığımız zaman derleyici hata vermeyecektir fakat program akışında hata almamız kaçınılmaz olur. Burada dikkat edilmesi gereken başka bir durum ise serialize olmasını istemediğimiz alanları [NonSerialized] olarak işaretlemektir.
BinaryFormatter serialization
Şimdi BinarySerialize adında bir sınıf ekleyip işlemleri yapacak olan methodları yazalım.Serialize & Deserialize işlemlerini Formatter yapısıyla sağlıyoruz. Formatter .net framework 1.1 ‘den beri bizimle olan bir yapı. Methodumuzu yazarken System.Runtime.Serialization.Formatters.Binary BinaryFormatter sınıfından faydalanacağız. BinaryFormatter sınıfı serialize methodunu stream edilen data üzerinden sağlar. Bu nedenle stream objemiz ve serialize edilecek nesneyi methoda parametre olarak göndermeliyiz. Biz işlemimizi memory’de yaptğımız için burada MemoryStream kulanıyoruz. Farklı bir işlemde dosya ile ilgili bir işlem yapıyor olsaydık bu defa FileStream, StreamWriter ,StreamReader gibi sınıfları kullanabilirdik. Methodumuza dönecek olursak BinaryFormatter serialize işlemini tamamlayınca geriye byte dizi dönmektedir. Bizde geriye byte dizi dönen bir method tanımladık ve işlemlerimizi gerçekleştirdik. Deserialize işlemi de yine formatter yardımıyla gerçekleşir. Bu defa method parametre olarak byte dizi alır geriye ise object döndürür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
namespace bilisim.io { public class BinarySerialization { public byte[] Serialize(object graph) { using (MemoryStream mStream = new MemoryStream()) { mStream.Position = 0; BinaryFormatter binaryFormatter = new BinaryFormatter(); binaryFormatter.Serialize(mStream, graph); return mStream.ToArray(); } } public object Deserialize(byte[] serialieByte) { using (MemoryStream mStream = new MemoryStream(serialieByte)) { IFormatter binaryFormatProvider = new BinaryFormatter(); return binaryFormatProvider.Deserialize(mStream); } } } } |
Program.cs içine methodları çağıran kod blogunu da ekleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
static void Main(string[] args) { BinarySerialization binarySerialization = new BinarySerialization(); Author author = new Author() { Name = "Burak", SurName = "Karadağ", }; Console.WriteLine("Author Data.."); Console.WriteLine(string.Format("Name:{0}, SurName:{1}, FullName:{2}", author.Name,author.SurName, author.FullName)); Console.WriteLine("Author Data Serialize Edildi.."); byte[] serializeData = binarySerialization.Serialize(author); Console.WriteLine("Data Serialize Edildi.."); Console.WriteLine(Convert.ToBase64String(serializeData)); Author deserializedAuthor = (Author)binarySerialization.Deserialize(serializeData); Console.WriteLine("Serialize data Deserialize Edildi.."); Console.WriteLine(string.Format("Name:{0}, SurName:{1}, FullName:{2}",deserializedAuthor.Name, deserializedAuthor.SurName, deserializedAuthor.FullName)); Console.ReadKey(); } |
Kodları inceleyecek olursak Author sınıfını kullanarak author isimli bir obje oluşturduk. Author objemizi oluştururken Object İnitializers özelliğinde faydalandık. Bu durum IDE’nin bize sunduğu güzellikler arasındadır. VisualStudio 2008 ile birlikte yazdığımız kodlar arasında yer edinmiştir. İsterseniz aşağıdaki gibi de tanımlama yapabilirsiniz.
1 2 3 4 5 6 |
Author author = new Author(); author.Name = “Burak”; |
Convert.ToBase64String methodu byte dizi ‘yi olduğu gibi string ‘e çevirir.
Programı çalıştırıp sonuca baktığımızda author sınıfını serialize ve deserialize edilmiş olarak görebilirsiniz.
XML(Extensible Markup Language, Genişletilebilir İşaretleme Dili) Serialization
- XML Serialization ile yapılan Serialize&Deserialize işlemlerinde tip güvenliği yoktur. Veriyi string olarak genel XML kurallarında işleyip döndürür. Serialization işlemlerinde XML ‘ in avantajı Cross Platform da ortaya çıkmaktadır.İşlem sonucumuz birden çok ortamda kullanılacaksa XML tercih sebebi olabilir. Serialize olmasını istemediğimiz bir değişkenimiz varsa bunları [XmlIgnore] ile işaretlememiz gerekmektedir. Serialize edilecek değişkenler [XmlElement] ile işaretlenir. Unutmadan eklemek gereken önemli bir durum ise Xml Serialize’ın private tanımlanmış değişkenleri serialize etmediğidir. Şimdi Örneğimizi biraz daha zengineştirip XMLSerialization sınıfımızı entegre edelim.
Projemize XMLSerialization adında yeni bir sınıf ekleyelim ve methodlarımızı yazalım.
Xml için eklediğim Serialize methodunda XmlSerializerNamespaces ile oluşturduğumuz xml ‘ i obje çeviri işlemine yakın hale getiriyoruz. Bu kodu kullanmadığımız zaman xmlns=”> was not expected.” hatası alırız.
Bizim örneğimiz nesne yi xml ‘e çevirip tekrardan nesne ‘ ye dönüşümünü sağlamak olduğundan bu xmlns ‘ e gerek duymuyoruz. Zorunlu olduğu senaryolarda XmlRoot attribute parametreleriyle istenilen yapıyı sağlayabiliriz. System.Xml ile gelen XmlWriter xml içeren dosya veya stream oluşturmak için kullanılır. Biz örneğimizi stream üzrinden kurduğumuz için oluşan stream’ i işleyebileceğimiz bir obje gerekiyor, bu obje StringWriter sınıfıdır. String işlemleri için kullanılan stream (akış , kanal) türüdür.
Daha önce eklediğimiz Author sınıfı üzerinde bazı değişiklikler yapmamız gerekecek. Yeni hali aşağıdak gibi olmalıdır.Author sınıfımız son haliyle birlikte hem binary hem Xml serialization’a uygun yapıya geldi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
namespace bilisim.io { [Serializable] public class Author { [XmlElement] public string Name; [XmlElement] public string SurName; [XmlElement] public string FullName { get { return string.Concat(Name, SurName); } set { } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public string Serialization(object graph) { XmlSerializerNamespaces xns = new XmlSerializerNamespaces(); xns.Add(string.Empty, string.Empty); XmlSerializer xSerializer = new XmlSerializer(graph.GetType()); using (StringWriter sWriter = new StringWriter()) { using (XmlWriter w = XmlWriter.Create(sWriter)) { xSerializer.Serialize(w, graph,xns); return sWriter.ToString(); } } } public object DeSerialization(string xmlStrig) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(Author)); using (StringReader sReader = new StringReader(xmlStrig)) { return (object)xmlSerializer.Deserialize(sReader); } } public string XmlBeautifier(string xmlString) { try { XDocument doc = XDocument.Parse(xmlString); return doc.ToString(); } catch (Exception) { return xmlString; } } |
Programı çalıştırıp sonuca baktığımızda author sınıfını serialize ve deserialize edilmiş olarak görebilirsiniz.
H.Burak Karadağ