1. Giriş
Çoxlu köhnə dərsliklərdə və C# üzrə nümunələrdə BinaryFormatter ilə serializasiya görmək olar. Bir zamanlar bu standart idi: rahat, sürətli, az problemlə. Köhnə dövrlərdən nümunə təxminən belə görünürdü:
// Təhlükəli köhnə kod! Yeni layihələrdə belə etməyin!
var bf = new BinaryFormatter();
using (var stream = File.Open("player.dat", FileMode.Create))
{
bf.Serialize(stream, playerObject);
}
Amma müasir .NET 9-da belə kodu artıq tərtib edə bilməyəcəksiniz: BinaryFormatter platformadan çıxarılıb.
Qəhrəmandan kənarlaşdırılana doğru yol
Əvvəl BinaryFormatter .NET obyektlərinin serializasiya və deserializasiyası üçün universal mexanizm kimi nəzərdə tutulmuşdu, mürəkkəb obyekt qraflarını "olduğu kimi" saxlaya bilirdi. Vaxt keçdikcə ciddi təhlükəsizlik və uyğunluq problemləri üzə çıxdı və indi o keçmişə qayıdıb — sanki kassetli maqnitafonlar streaming dövründə.
2. BinaryFormatter-dan imtinanın əsas səbəbləri
Geniş təhlükəsizlik deşik
BinaryFormatter yalnız məlumatları serializasiya etmir, həm də giriş axınından tipləri bərpa edir. Əgər doğrulanmamış məlumatı (məsələn, şəbəkədən alınanı) düşünmədən deserializasiya etsəniz, hücumçu zərərli yük yerləşdirə və uzaqdan kodun icrasına (RCE) səbəb ola bilər. Microsoft uzun illər xəbərdarlıq edirdi: «BinaryFormatter-dən istifadə etməyin». .NET 5-dən etibarən o deprecated və təhlükəli kimi işarələndi ([Obsolete]), .NET 9-da isə çıxarıldı.
Klassların daxili strukturundan asılılıq
BinaryFormatter formatı tipin implementasiya detalları — sahələr, boxing, versiyalar — ilə bağlıdır. Klassda ən kiçik dəyişiklik (sahə əlavə/çıxartma) artıq saxlanılan fayllarla uyğunluğu poza bilər. Bu formatı uzun müddətli saxlama və versiyalararası mübadilə üçün yararsız edir.
Çarpaz-platforma çətinlikləri
BinaryFormatter ilə yadda saxlanmış məlumatlar .NET obyektlərinin daxili təqdimatına bağlıdır. Bunu başqa platformada/dildə və ya hətta fərqli .NET versiyasında oxumaq çox vaxt mümkün deyil.
3. "Köhnə kod"u necə aşkar etmək və nə etmək lazımdır?
BinaryFormatter-dan istifadə əlamətləri belə görünür:
using System.Runtime.Serialization.Formatters.Binary; // <-- şübhəlidir!
BinaryFormatter bf = new BinaryFormatter(); // <-- təhlükəli!
bf.Serialize(...);
bf.Deserialize(...);
Müasir .NET versiyalarında bu kod tərtib olunmur: alətlər "Type or namespace name could not be found" tərzində səhv verəcək. Legacy .NET Framework layihələrində ən azı ciddi xəbərdarlıqlar göstəriləcək.
Əgər belə kodla rastlaşsanız, BinaryFormatter-ı müasir, təhlükəsiz alternativlərlə əvəz edin.
Bu gün hansı formatlar və klasslardan istifadə etmək lazımdır?
JSON üçün
- System.Text.Json — sürətli, təhlükəsiz, .NET-ə daxildir. Rəsmi sənəd
- Newtonsoft.Json — mürəkkəb hallar üçün məşhur üçüncü tərəf kitabxana.
XML üçün
- XmlSerializer — XML-ə serializasiya. Sənəd
Bayt formatları üçün
- System.Formats.Cbor (CBOR)
- Protobuf.Net (Protocol Buffers), MessagePack for C#
Xüsusi tapşırıqlar üçün uyğun format və kitabxana seçin — BinaryFormatter tərzində "ümumi" bir binary serializator artıq yoxdur və bu yaxşıdır.
4. BinaryFormatter-dan kodu necə yenidən yazmaq olar
BinaryFormatter-dan nəyə görə istifadə etmək olmaz
Olmaz:
- İstifadəçi ayarlarını və vacib məlumatları saxlamaq.
- Məlumatları şəbəkə üzərindən göndərmək (client ↔ server).
- Doğrulanmamış mənbələrdən alınmış məlumatları deserializasiya etmək.
Əvəzinə:
- Gündəlik ehtiyaclar üçün — System.Text.Json.
- Konfiqurasiyalar üçün — JSON, XML və s.
- Dillərarası mübadilə üçün — kross-platform uyğun formatlar (JSON, XML, Protobuf, MessagePack).
İndi necə kod yazmaq lazımdır?
JSON-ə serializasiya (tövsiyə olunan üsul)
using System.Text.Json;
// Sizin klass:
public class Player
{
public string Name { get; set; } = "";
public int Health { get; set; }
public bool IsAlive { get; set; }
}
// Serializasiya üçün obyekt
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
// Obyekti JSON sətrinə çeviririk
string json = JsonSerializer.Serialize(player);
// Fayla yazırıq — təhlükəsizdir!
File.WriteAllText("player.json", json);
// Obyekti fayldan bərpa etmək üçün:
string loadedJson = File.ReadAllText("player.json");
Player loadedPlayer = JsonSerializer.Deserialize<Player>(loadedJson)!;
XML-ə serializasiya (əgər sərt format lazımdırsa)
using System.Xml.Serialization;
// Klassin publik parametrsiz konstruktoru olmalıdır
var player = new Player { Name = "Aragorn", Health = 100, IsAlive = true };
var serializer = new XmlSerializer(typeof(Player));
using (var fs = File.Create("player.xml"))
{
serializer.Serialize(fs, player);
}
Vizual sxem «köhnə vs yeni»
| Vəzifə | Köhnə üsul (BinaryFormatter) | Müasir üsul |
|---|---|---|
| Fayla serializasiya | |
|
| Fayldan deserializasiya | |
|
| Təhlükəsizlik | Zərbələrə açıqdır (RCE) | Təhlükəsiz parserlər və sərt modellər |
| Çarpaz-platforma | Yox | Bəli (JSON/XML/Protobuf) |
| Sürət | Sürətli, amma təhlükəli | Sürətli və təhlükəsiz |
5. XmlSerializer ilə işləyərkən tipik səhvlər
Səhv №1: privat property və ya sahələr. XmlSerializer yalnız public property-ləri serializasiya edir; hətta protected da problem yarada bilər.
Səhv №2: default konstruktorun olmaması. Parametrsiz publik konstruktor olmalıdır, əks halda serializasiya/deserializasiya işləməyəcək.
Səhv №3: tip uyğunluğunun olmaması. XmlSerializer Dictionary, interface və delegate ilə pis işləyə bilər — wrapper-lər və ya başqa formatlardan istifadə edin.
Səhv №4: dövri istinadlar (circular reference). XmlSerializer A → B → A tipli qrafları dəstəkləmir; belə hallar üçün adətən uyğun konfiqurasiyalı JSON götürürlər.
GO TO FULL VERSION