Binary Serialization ve Versiyon Problemi

   C# ile hafızadaki bir nesneyi saklamak iserseniz (örneğin, dosya sisteminde ya da veritabanındaki bir tabloda) bu işlem için kullanabileceğiniz iki temel yaklaşım bulunmakta ve bu iki yöntemin de kendilerine göre artıları ve eksileri söz konusu;

  • Xml Serialization      : Birlikte işlerlik sizin için önemli ise şüphesiz ki ilk tercihiniz (hatta tek tercihiniz) xml serileştirme olacaktır. Bu önemli artısına karşın gerek fazla yer kaplaması, gerekse de serialization/deserialization işlemlerinde fazla işlemci zamanı ve hafıza tüketmesi eksi olarak düşülmeli.
  • Binary Serialization : Xml serileştirmesinin aksine birlikte işlerlik söz konusu ise  (özellikle C# ile diğer diller arasında) binary serileştirme seçeneğiniz olmamalı. Öte yandan xml serileştirmesine göre daha az yer kaplaması, düşük işlemci zamanı ve hafıza tüketimi artı hanesine yazılanlar.

   Bu iki yöntemi karşılaştırırken göz önüne almamız gereken bir başka önemli kriter de geriye uyumluluk olmalı. Bu konuda hiç şüphe yok ki Xml serileştirme de çok rahat edersiniz,.Binary serileştirmede nesneler barındırdıkları veriler dışında tür bilgileriyle birlikte saklanır. Bu durumda da kullandığınız kütüphanenin yeni sürümü ile eski serileştirilmiş verileri açmakta problem yaşarsınız.

   Eski serileştirilmiş veriler yeni kütüphaneyle açılmaya çalışıldığında, BinaryFormatter verinin serileştirilmesi sırasında kullanılan tür’ü içerisinde bulunduğu assambly adı ve tür adı ikilisi ile arayacaktır. Eğer application domain içerisinde bu tür bilgisi bulunmuyorsa/tür yüklenemiyorsa hata alarak işleminiz yarım kalacaktır. Serileştirilmiş veri içerisinde bulunan türlerin assembly adı ve tür adı ikilisi ile geri yükleniyor olması nedeniyle assembly adında, sürüm numarasında, genel anahtar simgesinde (public key token) ya da tür adında yapılacak en ufak bir değişiklik geriye dönük serileştirilmiş verilerin açılmasında büyük sıkıntıya neden olmakta.

   Bu noktada pek çok yazılımcı binary serileştirme için kullanılan türlerin bulunduğu assembly’nin sürüm numarasını, genel anahtar simgesini sabitleyerek ve tür içeriklerine dokunmayarak çözme yoluna gitmekte. Bu yöntem gerçek anlamda bir çözüm olmasa da çoğunlukla problemi ortadan kaldırmakta, daha doğrusu, üstünü örtmektedir. İşler, tür içeriğine dokunulduğunda, assembly sürüm numarası değiştiğinde ya da assembly bir anahtar ile imzalanarak bir genel anahtar simgesine sahip olduğunda zorlaşacaktır.

   Şanslıyız ki .Net framework tasarımı sırasında binary serileştirmede böylesi bir problem yaşanabileceği göz önüne alınarak ilk sürümünden beri pek bilinmeyen bir çözüm sunulmuş durumda : SerializationBinder. Binary serileştirme sırasında kullanılan BinaryFormatter sınıfı tür bilgilerini binder özelliğini kullanarak almaktadır. Yukarıdaki gibi bir değişiklik sonrasında serileştirilmiş veri içerisindeki tür bilgilerini farklı yorumlamanız gerektiğinde BinaryFormatter ile birlikte gelen varsayılan Binder’a müdahale ederek kendi tasarladığınız SerializationBinder’ı kullanabiliriz. Yapmanız gereken SerializationBinder sınıfından türeyen yeni bir tür oluşturarak serileştirilmiş veri içerisindeki tür bilgisinin sorgulandığı BindToType metodunun içerisine ihtiyacınız olan yönlendirme kodunu eklemek. Ardından bu sınıfın bir örneğini BinaryFormatter’ın Binder özelliğine atamak.

   Aşağıda kodunu bulabileceğiniz OzellesmisBinaryFormatter sizlerle paylaşmış olduğum yöntemi kullanan ve SerializationBinder sınıfından türetilmiş bir sınıftır. İçerisinde bir BinaryFormatter barındıran bu sınıf, BinaryFormatter’ın Binder özelliğine OzellesmisBinaryFormatter sınıf örneği atamaktadır. Bu örnekte 1f91253719787bdf genel anahtar simgesi ile serileştirmesi yapılmış bir verinin bu genel anahtar simgesinin 6496550b925512 olarak güncellenmesi sonrasında da açılabilmesi sağlanmıştır.

public class OzellesmisBinaryFormatter : SerializationBinder {
    private BinaryFormatter formatter;

    public OzellesmisBinaryFormatter() {
        formatter = new BinaryFormatter {
            Binder = this
        };
    }

    public object Deserialize(Stream serializationStream) {
        return formatter.Deserialize(serializationStream);
    }

    public void Serialize(Stream serializationStream, object graph) {
        formatter.Serialize(serializationStream, graph);
    }

    public override Type BindToType(string assemblyAdi, string turAdi) {
        if (assemblyAdi.EndsWith("PublicKeyToken=1f91253719787bdf")) {
            assemblyAdi = assemblyAdi.Replace("PublicKeyToken=1f91253719787bdf", "PublicKeyToken=6496550b925512");
        }

        Type tur = Type.GetType(String.Format("{0}, {1}", turAdi, assemblyAdi));

        return tur;
    }
}

   SerializationBinder sınıfından gelen ve deserialization sırasında framework tarafından kullanılan BindToType metodunu incelediğimizde string formatında gelen assembly ve tür adlarını kullanarak ilgili tür örneğinin dönüldüğünü görebiliriz. Gelen bilgiler içerisinde iş mantığımız doğrultusunda yapacağımız değişikliklerle serileştirme işlemi sırasında istediğiniz tür’e yönlendirme yapmamız mümkün. Bu yönlendirme neticesinde de geriye dönük olarak serileştirimiş verilerin açılması mümkün olmakta.

   SerializationBinder’ın tek kullanım amacı geriye dönüş uyumluluğun sağlanması değildir. Bu sınıf/yöntem kullanılarak istenirse 3.parti kaynaklardan gelen verilerin içerisinde istenmeyen türlerin iletilmesi de önlenerek yazılımımıza dışarıdan müdahale de önlenebilir ve güvenlik sağlanmış olur.

Fatih Boy

Ankara'da yaşayan Fatih, bir kamu kurumunda danışman olarak çalışmaktadır. ALM süreçleri, kurumsal veri yolu sistemleri, kurumsal altyapı ve yazılım geliştirme konularında destek vermektedir. Boş zamanlarında açık kaynak kodlu projeler geliştirmeyi ve bilgisini yazdığı makalelerle paylaşmayı seven Fatih, aynı zamanda Visual C# ve Visual Studio teknolojileri konusundan Microsoft tarafından altı yıl üst üste MVP (En Değerli Profesyonel) ödülüne layık görülmüştür. İş hayatı boyunca masaüstü uygulamaları, web teknolojileri, akıllı istemciler gibi konularda Asp.Net, Php, C#, Java programlama dilleri ve MySql, MsSql ve Oracle gibi veritabanı yönetim yazılımları ile çalışmıştır. İngilizce ve Türkçe olarak yayınlanan makalelerini gerek İngilizce bloğunda, gerekse de Türkçe bloğunda bulabileceğiniz gibi web sitesinden de açık kaynak kodlu geliştirdiği yazılımlarına ulaşabilirsiniz. vCard - Twitter - Facebook - Google+

Bir Cevap Yazın

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