Простая сериализация
Прежде всего импортируйте пространство имен 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
Применение
сериализации при клонировании объектов
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
Практический
пример: динамический список с поддержкой сериализации
В настоящем примере мы создаем менеджера (класс 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