C# ile serileştirme (serialization)

24 Ara

Veri merkezli uygulamalarda verileri saklamak veya transfer etmek gibi durumlarla sık sık karşılaşırız. Verilerin bir kaynaktan alınması veya bir yere depolanması nesneler aracılığı ile gerçekleştirilir. Ancak her programlama dilinde farklı yani platformda kendine özgü bir nesne yapısı olduğundan dolayı, bir platformun diğerinin nesne yapısını bilmesi beklenemez. Bu gibi durumlarda verilerin platform bağımsız bir şeklide depolanması veya transfer edilmesi amacıyla bazı standartlar oluşturulmuştur. Bu standartlardan bazıları Binary, Simple Object Access Protocol(SOAP), JSON veya XML şeklinde belirlenmiştir.

Serileştirme nedir?

Bir nesnedeki verinin bir yerde depolaması veya ağ ortamında bir yerden bir yere gönderilmesi gerektiği durumlarda uygun formata dönüştürülmesi işlemine serileştirme denir. Serileştirilen nesneler veritabanı, hafıza veya dosya gibi ortamlarda saklanabilirler.

serialization

 

 

 

 

 

Deserialization ise bu işlemin tam tersidir.

.Net Framework ile serileştirme

Serileştirme işlemini ve serileştirilmiş nesneleri dönüştürme işlemini gerçekleştirecek olan nesneler, System.Net.Runtime.Serialization ad uzayında bulunmaktadır. Serialization işlemi, bir nesneyi, depolamak veya serileştirmek amacıyla istenen formata dönüştürme işlemidir. Deserialization ise serileştirilmiş biçimdeki verilerin tekrar nesnelere dönüştürülmesi işlemidir. Örneğin, network ortamında bir bilgisayardan başka bir bilgisayara veri transferi gerçekleştirmek için önce bağlantı kurulur, ardından gönderilecek olan nesne oluşturduğumuz uygulama tarafından serileştirilir, daha sonra uzak bilgisayardaki uygulama tarafından deserialization işlemi ile aktarılan veri anlamlı bir nesneye dönüştürülür.

  1. Binary Serialization
  2. SOAP Serialization
  3. JSON Serialization

1-Binary Serialization / Deserialization (İkili Serileştirme)

Binary serişeltirme işlemi için gerekli olan sınıflar  System.Runtime.Serialization.Formatters.Binary altında bulunurlar.

  • Binary serialization işleminde nesneler byte array şekline dönüştürülür.
  • Binary deserialization işleminde byte array şeklindeki tekrar nesneye dönüştürülür.
 public static byte[] BinarySerialize(object graph)
 {
     using (var stream = new MemoryStream())
     {
         var formatter = new BinaryFormatter();
 
         formatter.Serialize(stream, graph);

         return stream.ToArray();
     }
 }

 public static object BinaryDeserialize(byte[] buffer)
 {
     using (var stream = new MemoryStream(buffer))
     {
        var formatter = new BinaryFormatter();

        return formatter.Deserialize(stream);
     }
 }

Burada binary serialization işlemini gerçekleştiren BinaryFormatter sınıfıdır. BinaryFormatter sınıfı parametre olarak bir Stream nesnesi aldığı için MemoryStream kullanılmıştır.

Örnek: Serileştirme işlemi sırasında kullanılacak olan veri tipimiz PlaceOrder isminde bir sınıf olsun.


 [Serializable]
 public class PlaceOrder
 {
     public Guid Id { get; set; }
 }

Bu sınıfa ait bir verinin serileştirme işlemi şu şekilde gerçekleştirilir.


 public class Program
 {
     static void main(string[] args)
     {
         PlaceOrder order = new PlaceOrder();
         var seralized = BinarySerialize(order);
         var deserialized = BinaryDeserialize(serialized);
     }
 }

Not: Yukarıdaki örnekte PlaceOrder sınıfı [Serializable] attribute ile işaretlenmiş ve serileştirilebilir hale getirilmiştir. Bu işaretleme BinaryFormatter kullanarak yapılan serileştirme işlemlerinde zorunludur. Aksi taktirde runtime esnasında SerializationException hatası oluşacaktır.

serializationexception

Serileştirilebilir sınıflar nasıl oluşturulur?

Bir sınıfa ait nesneleri serileştirilebilir hale getirmek için sınıfa ait nesnelerin [Serializable] ile imzalanması gerekmektedir. Serileştirme işlemini gerçekleştirdiğinizde runtime esnasında private erişimli üyeler dahil tüm sınıf üyeleri serileştirilir.

Örnek:

    [Serializable]
    public class PlaceOrder
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

Sınıf içersinde bir üyeyi serileştirmeden hariç tutmak için o üyenin [NonSerialized] ile imzalanması gerekmektedir.

Örnek:

    [Serializable]
    public class PlaceOrder
    {
        public Guid Id { get; set; }
        [NonSerialized]
        public string Name { get; set; }
    }

Bu şekilde Name üyesi serileştirme işlemine dahil edilmeyecektir.
Serileştirilmemiş nesneler ile deserialization işlemi sonrası işlem yapmak için IDeserializationCallback.OnDeserialization metodunu çağırarak, bu metod içerisinde istenen işlemleri gerçekleştirebiliriz.

Örnek:

    [Serializable]
    public class ShoppingCartItem: IDeserializationCallback
    {
       public string Name { get; set; }
       public int Quantity { get; set; }
       public decimal ListPrice { get; set; }
       [NonSerialized]
       public decimal Total;

       #region IDeserializationCallback Members
        public void OnDeserialization(object sender)
        {
           Total=Quantity*ListPrice;
        }
       #endregion
    }

2-SOAP Serialization / Deserialization (SOAP Serileştirme)

Bir nesnenin Simple Object Access Protocol(SOAP) protokolü üzerinden transfer edilebilmesi için bu protokole uygun bir şekilde serileştirilmesi ve serileştirilen nesnenin tekrar nesneye dönüştürülmesi işlemleridir. SOAP serileştirme işlemleri için gerekli sınıflar System.Runtime.Serialization.Formatters.Soap altında bulunurlar.

 
   public static string SoapSerialize(object graph)
  {
     using (var stream = new MemoryStream())
     {
        var formatter = new SoapFormatter();

        formatter.Serialize(stream, graph);
 
        return Encoding.UTF8.GetString(
                  stream.GetBuffer(), 0, (int)stream.Position);
     }
  }

  public static object SoapDeserialize(string buffer)
  {
     using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(buffer)))
     {
         var formatter = new SoapFormatter();

         return formatter.Deserialize(stream);
     }
  }

Örnek: SOAP serileştirilmiş bir nesnenin görünümü:


 public class Program
 {
     static void main(string[] args)
     {
         PlaceOrder order = new PlaceOrder
         {
             Id = Guid.NewGuid()
         };
         var soapseralized = SoapSerialize(order);
         var soapdeserialized = SoapDeserialize(soapserialized);
     }
 }

soap serialization

3- JSON Serialization

Nesneleri JSON şeklinde serileştirme işlemi için Json.Net kütüphanesi kullanılabilir. Bu kütüphane nuget paketi olarak bu adresten indirilebilir.

 
  public static string JsonSerialize(object graph)
  {
      return JsonConvert.SerializeObject(graph);
  }

  public static object JsonDeserialize(string seralized)
  {
      return JsonConvert.DeserializeObject(seralized);
  }

Örnek JSON serileştirilmiş nesne.
json

Not: Json serileştirme sonucunda .Net ile ilgili bilgiler Json nesnesine eklenmez. Örneğin nesnenin hangi namespace ve hangi sınıfa ait olduğu bilgisi yoktur. Bu bilgilerinde eklenmesini istiyorsanız JsonSerializerSettings sınıfını serileştirme ve deserileştirme işlemi sırasında kullanmalısınız. JsonSerializerSettings sınıfının TypeNameHandling üyesi TypeNameHandling.Objects şeklinde düzenlenmelidir.

 
 public static string JsonSerialize(object graph)
 {
     return JsonConvert.SerializeObject(graph, 
         Formatting.None, 
         new JsonSerializerSettings
         {
            TypeNameHandling = TypeNameHandling.Objects
         });
 }

 public static object JsonDeserialize(string seralized)
 {
     return JsonConvert.DeserializeObject(seralized, 
         new JsonSerializerSettings
         {
            TypeNameHandling = TypeNameHandling.Objects
         });
 }

json

[Serializable] Attribute Kullanmadan Binary Serileştirme

BinaryFormatter veya SoapFormatter kullanarak serileştirme işlemleri gerçekleştirilen sınıfların [Serializable] attribute ile imzalanması gerektiğini söylemiştik. Ancak Json serileştirme yaparken sınıfların [Serializable] attribute ile imzalanmasına gerek yoktur.


 public class PlaceOrder
 {
     public Guid Id { get; set; }
 }

PlaceOrder sınıfına ait nesneler JsonConvert ile [Serializable] attribute olmadan serileştirilebilir.

Bu durumda eğer BinaryFormatter veya SoapFormatter gibi serileştirme işlemlerinden önce JsonConvert ile serileştirme yapılıp ardından binary serileştirme yapıldığında sınıfların [Serializable] attribute ile imzalanmasına gerek kalmaz.

Örnek:


 public static byte[] BinarySerializeWitoutSerializable(object graph)
 {
   using (var stream = new MemoryStream())
   {
      var formatter = new BinaryFormatter();

      formatter.Serialize(stream, JsonConvert.SerializeObject(graph));

      return stream.ToArray();
   }
 }

Ancak bu durumda art arda iki defa serileştirme işlemi gerçekleştirilmiş olur.

2 thoughts on “C# ile serileştirme (serialization)

Comments are closed.