Làm quen với .NET Serialization
Trong .net hỗ trợ nhiều cách khác nhau để serialize dữ liệu, tất cả đều có chung mục đích là serialize object, nhưng điểm khác biệt là format output sẽ khác nhau. Các hàm dùng để serialize object trong .net có thể được gọi là formatter hoặc serializer và có thể phân loại theo 3 prefix là:
Serializer như: XmlSerializer, DataContractSerializer, JavaScriptSerializer
Formatter như: BinaryFormatter, SoapFormatter
Reader như: XamlReader
Hoặc thậm chí là từ thư viện thứ ba như JSON.NET
Ta sẽ bắt đầu với gia phả nhà Formatter để làm quen với quá trình Serialize trong .net
Formatter
Đối với formatter thì có 3 loại phổ biến:
BinaryFormatter:cho ra kết quả là binary
SoapFormatter:cho ra kết quả dưới dạng soap format
ObjectStateFormatter:dùng với ViewState
Để một object có thể serialize, ta chỉ cần thêm attribute [Serializable]
(không giống như Java phải implement lại Serializable interface)
Ví dụ một object có thể serialize
Khi deser ta sẽ lưu kết quả vào file data.bin
, ta có thể thấy dữ liệu được lưu vào file data.bin là dạng binary
Còn khi deser ta sẽ có kết quả
Magic Methods
Trong quá trình serialize và deserialze đương nhiên sẽ có những magic method được gọi, đối với .net thì những magic method sẽ được gọi là callback method trong quá trình seri/deser
Cụ thể quá trình seri/deser diễn ra như thế nào thì có thể tham khảo: dotnet-serialize-101.mdY4er/dotnet-deserialization
Trong .NET một Object Serialize sẽ có 4 magic method cơ bản như sau:
OnSerializing: được gọi trước khi quá trình Serialize diễn ra
OnSerialized: được gọi khi hoàn thành quá trình Serialize
OnDeserializing: được gọi trước khi quá trình Deserialize diễn ra
OnDeserialized: được gọi khi hoàn thành quá trình Deserialize
Code ví dụ:
Khi seri và deser Object trên ta được kết quả
Ngoài 4 methods trên thì nếu khi ta implement lại một số interface có hỗ trợ serialize ta sẽ có thêm nhiều magic methods khác, ví dụ như khi implement ISerializable interfaces thì ta phải implement lại constructor và method GetObjectData
, và method này sẽ được gọi trong quá trình serialize
Code ví dụ:
Kết quả:
Lưu ý: ta có thể thấy khi implement 2 methods trên ta cần phải khai báo kèm theo SerializationInfo
class, nguyên nhân của việc này là .net cho phép ta có thể can thiệp vào quá trình seri hoặc deser thông qua SerializationInfo. SerializationInfo giống như một biến đại diện cho thông tin của seri stream, mọi thông tin như type, giá trị của object trong quá trình seri/deser đều được lưu trong này
Tóm tắt:
Ngoài ra thằng Formarter còn có tính năng cho phép ta serialize object có type không hỗ trợ. Ta có thể làm điều đó với interface ISerializationSurrogate
. Ta có thể hình dung Interface này giống như một “người đại diện” giúp ta có thể serialize được object type mà Formarter không hỗ trợ. Ví dụ mình có object Person
, là một object bình thường không sử dụng attribute [Serialize]
Đây hoàn toàn là object type mà Formatter không thể serialize, do đó ta sẽ khai báo thêm một class để làm “đại diện” cho Class Person này khi thực hiện serialize
Khi implement ISerializationSurrogate
ta sẽ phải khai báo 2 method là:
GetObjectData: được gọi khi serialize
SetObjectData: được gọi khi deser
Để Formarter có thể sử dụng được ISerializationSurrogate
ta tiến hành khai báo tại hàm main như sau:
Mình sẽ khai báo 2 instance của BinaryFormatter
và SurrogateSelector
. Sau đó dùng method AddSurrogate
để khai báo object type nào sẽ được PersonSerializeSurrogate
làm “đại diện”, ở đây mình sẽ có type của Person
Chi tiết các agrument của method AddSurrogate
Tiếp theo mình add “đại diện” vào Formatter và tiến hành serialize như bình thường, mình ghi kết quả ra file để so sánh kết quả khi dùng ISerializationSurrogate
và khi không dùng
Các bạn có thể thấy object được serialize thông qua ISerializationSurrogate
không khác gì một object được serialize trực tiếp như bình thường
Về thứ thự gọi callback methods trong việc serialize thông qua “đại diện” thì GetObjectData
sẽ nằm giữa OnSerializing và OnSerialized, còn SetObjectData
thì nằm giữa OnDeserializing và OnDeserialized
Tóm tắt quá trình seri của Formatter sẽ như sau
Last updated