CodeGym /Kurslar /C# SELF /Müzakirə edirik BinaryFormatter

Müzakirə edirik BinaryFormatter

C# SELF
Səviyyə, Dərs
Mövcuddur

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
bf.Serialize(stream, obj)
JsonSerializer.Serialize(...)
XmlSerializer.Serialize(...)
Fayldan deserializasiya
bf.Deserialize(stream)
JsonSerializer.Deserialize<T>(...)
XmlSerializer.Deserialize(...)
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.

2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Sadə obyekt üçün JSON və XML serializasiyasının müqayisəsi
Sadə obyekt üçün JSON və XML serializasiyasının müqayisəsi
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION