Có hai thứ gọi là hàm tạo (hoặc ít nhất là phải làm).
Một là dành một lượng bộ nhớ nhất định cho đối tượng và thực hiện tất cả các dịch vụ cần thiết để nó trở thành đối tượng cho phần còn lại của thế giới .NET (lưu ý một số lượng handwaving nhất định trong giải thích này).
Cách khác là đặt đối tượng vào trạng thái ban đầu hợp lệ, có lẽ dựa trên các tham số - đây là những gì mã thực tế trong hàm tạo sẽ thực hiện.
Deserialisation thực hiện tương tự như bước đầu tiên bằng cách gọi FormatterServices.GetUninitializedObject
và sau đó thực hiện tương tự như bước thứ hai bằng cách đặt giá trị cho trường tương đương với giá trị được ghi lại trong quá trình tuần tự hóa (có thể yêu cầu deserialising các đối tượng khác để nói giá trị).
Bây giờ, trạng thái deserialisation được đưa các đối tượng vào có thể không tương ứng với điều đó có thể bởi bất kỳ nhà xây dựng. Tốt nhất là nó sẽ lãng phí (tất cả các giá trị được thiết lập bởi các nhà xây dựng sẽ được ghi đè) và tồi tệ hơn nó có thể nguy hiểm (constructor có một số tác dụng phụ). Nó cũng có thể chỉ là không thể (chỉ constructor là một trong đó có tham số - serialization không có cách nào để biết những gì các đối số để sử dụng).
Bạn có thể xem nó như là một loại hàm tạo đặc biệt chỉ được sử dụng bởi deserialisation (OO purists sẽ - và nên rùng mình với ý tưởng về một constructor không xây dựng, ý tôi là chỉ tương tự, nếu bạn biết C++ nghĩ về cách ghi đè new
hoạt động như xa như bộ nhớ đi và bạn đã có một tương tự tốt hơn, mặc dù vẫn chỉ là một tương tự). Bây giờ, điều này có thể là một vấn đề trong một số trường hợp - có thể chúng tôi có readonly
trường chỉ có thể được đặt bởi một nhà xây dựng hoặc có thể chúng tôi có các tác dụng phụ mà chúng tôi muốn xảy ra.
Giải pháp cho cả hai là ghi đè hành vi tuần tự hóa với ISerializable
. Điều này sẽ nối tiếp dựa trên một cuộc gọi đến ISerializable.GetObjectData
và sau đó gọi một hàm tạo cụ thể với các trường SerializationInfo
và StreamingContext
để deserialise (cho biết hàm tạo thậm chí có thể là riêng tư - có nghĩa là hầu hết các mã khác thậm chí sẽ không nhìn thấy nó). Do đó nếu chúng ta có thể deserialise readonly
lĩnh vực và có bất kỳ tác dụng phụ chúng tôi muốn (chúng tôi cũng có thể làm tất cả các cách thức của những thứ để kiểm soát chỉ là những gì được serialized và làm thế nào).
Nếu chúng ta chỉ quan tâm đến việc đảm bảo một số tác dụng phụ xảy ra khi deserialisation xảy ra khi xây dựng, chúng tôi có thể thực hiện IDeserializationCallback
và chúng tôi sẽ có IDeserializationCallback.OnDeserialization
được gọi là khi quá trình deserialisation hoàn tất.
Đối với những thứ khác thực hiện tương tự như vậy, có các dạng tuần tự hóa khác trong .NET nhưng đó là tất cả những gì tôi biết. Bạn có thể tự gọi FormatterServices.GetUninitializedObject
nhưng chặn một trường hợp mà bạn có một đảm bảo mạnh mẽ rằng mã tiếp theo sẽ đặt đối tượng được tạo thành trạng thái hợp lệ (nghĩa là loại tình huống bạn đang ở trong khi deserialising một đối tượng từ dữ liệu được tạo ra bởi serialising giống nhau loại đối tượng) làm như vậy là đầy đủ và là cách tốt để tạo ra lỗi thực sự khó chẩn đoán.
Nguồn
2010-11-30 12:40:10
Tốt câu hỏi. Để làm việc xung quanh điều này, bạn sẽ cần phải làm một số con trỏ/tham chiếu fixups trong deserialization, mà có thể là khó khăn hoặc thậm chí không thể. Lưu ý thực tế rằng 'xe mới' chỉ được gọi một lần. Bạn có thể muốn thử điều này trong 2 quy trình. – leppie
bản sao có thể có của [DataContractSerializer không gọi hàm tạo của tôi?] (Http://stackoverflow.com/questions/1076730/datacontractserializer-doesnt-call-my-constructor) –
Lưu ý: Câu hỏi khác mà tôi liên kết là về DataContractSerializer , nhưng lời giải thích là như nhau cho BinaryFormatter –