|
|||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||
|
Проста
серіалізация
Перш за все
імпортуйте простір імен System.Runtime.Serialization, це заощадить немало
часу на введенні імен. У типовій ситуації підтримка серіалізациі включається
простим додаванням атрибуту в заголовок класу: <Serializable()>Public
Class Employee
Атрибут <Serial izable( )> має бути встановлений і у всіх класах, похідних
від вашого класу, а також у всіх вкладених класах, об'єкти яких містяться
в початковому класі. Інакше рекурсивний процес буде порушений з виключенням System.Runtime.Serialization.Serial
izationexception. Після
позначки класу атрибутом <Serial izablec )> слід вирішити, в якому форматі
повинен зберігатися об'єкт — в XML-формате SOAP або в компактнішому двійковому форматі.
Використовуваний за умовчанням двійковий формат доступний завжди. Щоб скористатися
форматом SOAP, необхідно додати посилання на збірку System. Runti me. Sena1izati
on. Formatters. Soap. Наступний
приклад показує, як організувати серіалізацию для масиву. Масив Arraylist
є об'єктом і може містити інші об'єкти (у нашому прикладі це об'єкти
ієрархії Employee). Оскільки динамічні масиви сері-алізуются автоматично,
залишається лише помітити атрибутом <Serializabl е( )> різні класи ієрархії
Empl oyee. Вся змістовна робота виконується в двох виділених рядках: Sub Serializetobinary(Byval myemployees As Arraylist._ Byval fname As String) Dim
fstream As Filestream Dim mybinaryformatter As New Formatters.Binary.BinaryFormatter() Try fstream = New
Filestreamtfname,filemode.Create, Fileaccess.Write) mybinaryformatter.Serialize(fstream, myemployees) Catch e
As Exception Throw e
Finally If Not (fstream Is Nothing) Then fstream.Close() End Try End Sub Щоб замість
двійкового формату масив зберігався у форматі SOAP, досить включити в проект
посилання на збірку System.Runtime.Serialization.Formatters.Soap (це робиться
в діалоговому вікні Project > References) і привести виділені рядки
до наступного вигляду: Dim mysoapformatter
As New Formatters.Soap.SoapFormatter() і mysoapformatter.Serialize(fstream.
myemployees) На мал. 9.4
показано, як виглядає отриманий файл у форматі SOAP.
З відновленням
збереженого об'єкту справа йде складніше: оскільки при десеріалізациі повертається
тип Object, доводиться виконувати явне перетворення до потрібного типу, як у
виділеному рядку наступного фрагмента: Function Deserializefromsoap(Byval
fname As String) As Arraylist Dim fstream
As New Filestreamtfname.FileMode.Open. Fileaccess.Read) Dim mysoapformatter
As New Formatters.Soap.SoapFormatter() Try fstream = New
Filestream("C:\test.xml". Filemode.Open. Fileaccess.Read) Return Ctype(mysoapformatter.Deserialize(fstream), Arraylist) Catch e
As Exception Throw e
Finally If Not (fstream Is Nothing) Then fstream.Close() End Try End
Function
Мал.
9.4. Об'єкт,
збережений у форматі SOAP
Застосування
серіалізациі при клонуванні об'єктів
У серіалізациі
є і таке нетривіальне застосування, як клонування складних об'єктів.
Фокус полягає в тому, щоб записати об'єкт в потік пам'яті Memorystream і
потім відновити його (потоки Memorystream дозволяють працювати з даними в швидкій
оперативній пам'яті по аналогії з тим, як потік Filestream працює з файлом
на диску). Нижче приведений типовий код клоніро-ванія: Public Function
Clone()As Object Implements Icloneable.Clone Dim mybinaryformatter As New Formatters.Binary.BinaryFormatter() Try Seriali'zetobinary()
mstream.Position = 0 Return mybinaryformatter.Deserialize(mstream)
Finally mstream.Close() End Try End Function Sub Serializetobinary() Dim mybinaryformatter As New Formatters.Binary.BinaryFormatter() Try mstream = New Memorystream() mybinaryformatter.Serialize(mstream.Me) Catch Throw End Try End Sub
Практичний
приклад: динамічний список з підтримкою серіалізациі
Перш ніж приводити повний
код прикладу, ми хочемо попередити про одну потенційну трудність, яка постійно
виникає при відновленні збережених об'єктів, а особливо об'єктів, що
зберігаються в динамічних списках. Отже, після завершення відновлення ми
отримуємо набір узагальнених об'єктів, що зберігаються в динамічному масиві.
Але як визначити дійсний тип цих об'єктів, щоб виконати правильне перетворення?
У наступному прикладі ця інформація жорстко фіксується в процесі відновлення,
оскільки ми точно знаємо порядок занесення об'єктів ієрархії Employee в масив.
У більш загальній ситуації ці відомості довелося б зберігати в окремому файлі. У справжньому
прикладі ми створюємо менеджера (клас Manager) з ім'ям Sally і секретаря (клас
Secretary) з ім'ям Той. Клас Manager містить внутрішній об'єкт класу Secretary
в одній із змінних; клас Secretary містить посилання на Manager. Нижче приведений
код тестової частини програми. Три ключові рядки виділено жирним шрифтом: Option
Strict On ' Використовує
збірку System.Runtime.Serialization.Formatters.Soap Imports System.IO Imports System.Runtime.Serialization Imports System.Runtime.Serialization.Formatters Module
Modulel Sub Main() Dim Sally As
New Manager("Sally". 150000) Dim Tom
As Secretary Tom = New Secretary("Tom".
100000, Sally) Sally.MySecretary
= Tom Dim Employees As New Arraylist() Employees. Add(Tom) Employees.Add(Sally) Console.WriteLine(Tom.TheName
& "is employee " & _ Tom.ThelD & "and has salary " & Tom.Salary) Console.WriteLine("Tom's boss is " & Tom.MyManager.TheName) Console.WriteLine("Sally's secretary is " & Sally.MySecretary.TheName) Console. Writeline()
Console.Writel_ine(Sally.TheName & "is employee " & _ Sally.ThelD & "has salary " & Sally.Salary) Sally.RaiseSalary(0.lD) Console.WriteLinet"After
raise " & Sally.TheName &_ "has salary "_ & Sally.Salary)
Ріс.9.5. Серіалізация динамічного масиву Нижче приведена
решта частини коди цього прикладу. Sub Serializetosoap(Byval myemployees As Arraylist._ Byval fname As String) Dim
fstream As Filestream Dim mysoapformatter As New Formatters.Soap.SoapFormatter() Try fstream = New Filestreamtfname. Filemode.Create.FileAccess.Write) mysoapformatter.Serialize(fstream. myemployees) Catch Throw
Finally If Not (fstream Is Nothing) Then fstream.Close() End Try End
Sub Function Deserializefromsoap(Byval
fname As String) As Arraylist Dim fstream
As New Filestream(fname. Fi1emode.Open. Fileaccess.Read) Dim mysoapformatter
As New Formatters.Soap.SoapFormatter() Try fstream = New Filestream(fname, Filemode.Open. Fileaccess.Read) Return Ctype(mysoapformatter.Deserialize(fstream), Arraylist) Catch Throw
Finally If Not (fstream Is Nothing) Then fstream.Close() End Try End Function End
Module <Serializable()>Public
Class Employee Private
m_name As String Private
m_salary As Decimal Private Const
LIMIT As Decimal = 0.1d Private
Shared m_employeeid As Integer = 1000 Private
m_myid As Integer Public Sub New(Byval
sname As String. Byval cursalary As Decimal) m_name =
sname m_salary
= cursalary m_myid =
m_employeeid m_employeeid = m_employeeid + 1 End Sub Readonly
Property THEIDO As Integer Get Return
mjnyid End Get End Property
Readonly Property Thename()As String Get Return
m_name End Get End Property
Readonly Property Salary()As Decimal Get Return Myclass.m_Salary End Get End Property Public Overridable Overloads Sub
Raisesalary(Byval Percent As Decimal) If Percent > LIMIT Then ' Неприпустима операція Console.WriteLineC'MUST
HAVE PASSWORD " & _ "TO RAISE
SALARY MORE THAN LIMIT!!!!") Else m_salary = (1 + Percent) * m_salary End If End
Sub Public Overridable Overloads Sub Raisesa1ary(Byval Percent As Decimal._ Byval Password
As String) If Password = "special" Then m_salary = (1 + Percent) * m_salary End If End Sub End
Class <Serializable()>Public
Class Manager Inherits
Employee Private
m_sec As Secretary Private
m_salary As Decimal Public Sub New(Byval sname As String,_ Byval cursalary
As Decimal) Mybase.New(sname. cursalary) End Sub Public Sub New(Byval
sname As String.ByVal cursalary As Decimal. Byval mysec As Secretary) Mybase.New(sname.curSalary) m_sec = mysec End
Sub Property Mysecretary()As
Secretary Get Return m_sec
End Get Set(Byval Value As Secretary) m_sec = Value End Set End Property Public Overloads Overrides Sub Raisesalary(Byval
percent As Decimal) Mybase.RaiseSalary(2 * percent, "special") End Sub End
Class <Serializable()> Public
Class Secretary Inherits Employee Private
m_boss As Manager Public Sub New(Byval
sname As String. Byval cursalary As Decimal Byval myboss As Manager) Mybase.New(sname, cursalary) m_boss = myboss End
Sub Property Mymanager()
As Manager Get Return m_boss End Get Set(Byval
Value As Manager) m_boss = Value End Set End Property End Class
|
|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||