Author:水如烟
配置类或数据类都需要可序列化。通常,序列化有三种方式,序列化和反序列化的过程可以做成一个静态类,如下:
Public Class SerializeHelper
Private Sub New()
End Sub
Private Shared Function GetXML(ByVal obj As Object) As String
Dim mSerializer As New System.Xml.Serialization.XmlSerializer(obj.GetType)
Dim mStringWriter As New System.IO.StringWriter
mSerializer.Serialize(mStringWriter, obj)
Return mStringWriter.ToString
End Function
Private Shared Function GetObj(ByVal objtype As Type, ByVal xml As String) As Object
Dim mSerializer As New System.Xml.Serialization.XmlSerializer(objtype)
Dim mStringReader As New System.IO.StringReader(xml)
Return mSerializer.Deserialize(mStringReader)
End Function
Private Shared Sub SaveXmlFile(ByVal filename As String, ByVal obj As Object)
Dim XmlWriter As New System.IO.StreamWriter(filename, False)
XmlWriter.Write(GetXML(obj))
XmlWriter.Close()
End Sub
Private Shared Function LoadXmlFile(ByVal filename As String, ByVal objtype As Type) As Object
Dim XmlReader As New System.IO.StreamReader(filename, System.Text.Encoding.Default)
Dim mObj As Object
mObj = GetObj(objtype, XmlReader.ReadToEnd)
XmlReader.Close()
Return mObj
End Function
Private Shared Sub SaveSerializerFile(ByVal filename As String, ByVal formatter As System.Runtime.Serialization.IFormatter, ByVal obj As Object)
Dim mFileStream As System.IO.Stream = System.IO.File.Open(filename, System.IO.FileMode.Create)
formatter.Serialize(mFileStream, obj)
mFileStream.Close()
End Sub
Private Shared Function LoadDeSerializeFile(ByVal FileName As String, ByVal formatter As System.Runtime.Serialization.IFormatter) As Object
Dim mFileStream As System.IO.Stream = System.IO.File.Open(FileName, System.IO.FileMode.Open)
Dim mObj As Object
mObj = formatter.Deserialize(mFileStream)
mFileStream.Close()
Return mObj
End Function
Public Shared Function Clone(ByVal obj As Object) As Object
Dim mFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim mMemoryStream As New System.IO.MemoryStream
mFormatter.Serialize(mMemoryStream, obj)
mMemoryStream.Position = 0
Return mFormatter.Deserialize(mMemoryStream)
End Function
Public Shared Sub Save(ByVal filename As String, ByVal formattype As FormatType, ByVal obj As Object)
Select Case formattype
Case formattype.Binary
SaveSerializerFile(filename, New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter, obj)
Case formattype.Soap
SaveSerializerFile(filename, New System.Runtime.Serialization.Formatters.Soap.SoapFormatter, obj)
Case formattype.Xml
SaveXmlFile(filename, obj)
End Select
End Sub
Public Shared Function Load(ByVal filename As String, ByVal formattype As FormatType, ByVal XmlFormatObjType As Type) As Object
Select Case formattype
Case formattype.Binary
Return LoadDeSerializeFile(filename, New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)
Case formattype.Soap
Return LoadDeSerializeFile(filename, New System.Runtime.Serialization.Formatters.Soap.SoapFormatter)
Case formattype.Xml
Return LoadXmlFile(filename, XmlFormatObjType)
End Select
Return Nothing
End Function
Public Enum FormatType
Xml
Binary
Soap
End Enum
End Class
Private Sub New()
End Sub
Private Shared Function GetXML(ByVal obj As Object) As String
Dim mSerializer As New System.Xml.Serialization.XmlSerializer(obj.GetType)
Dim mStringWriter As New System.IO.StringWriter
mSerializer.Serialize(mStringWriter, obj)
Return mStringWriter.ToString
End Function
Private Shared Function GetObj(ByVal objtype As Type, ByVal xml As String) As Object
Dim mSerializer As New System.Xml.Serialization.XmlSerializer(objtype)
Dim mStringReader As New System.IO.StringReader(xml)
Return mSerializer.Deserialize(mStringReader)
End Function
Private Shared Sub SaveXmlFile(ByVal filename As String, ByVal obj As Object)
Dim XmlWriter As New System.IO.StreamWriter(filename, False)
XmlWriter.Write(GetXML(obj))
XmlWriter.Close()
End Sub
Private Shared Function LoadXmlFile(ByVal filename As String, ByVal objtype As Type) As Object
Dim XmlReader As New System.IO.StreamReader(filename, System.Text.Encoding.Default)
Dim mObj As Object
mObj = GetObj(objtype, XmlReader.ReadToEnd)
XmlReader.Close()
Return mObj
End Function
Private Shared Sub SaveSerializerFile(ByVal filename As String, ByVal formatter As System.Runtime.Serialization.IFormatter, ByVal obj As Object)
Dim mFileStream As System.IO.Stream = System.IO.File.Open(filename, System.IO.FileMode.Create)
formatter.Serialize(mFileStream, obj)
mFileStream.Close()
End Sub
Private Shared Function LoadDeSerializeFile(ByVal FileName As String, ByVal formatter As System.Runtime.Serialization.IFormatter) As Object
Dim mFileStream As System.IO.Stream = System.IO.File.Open(FileName, System.IO.FileMode.Open)
Dim mObj As Object
mObj = formatter.Deserialize(mFileStream)
mFileStream.Close()
Return mObj
End Function
Public Shared Function Clone(ByVal obj As Object) As Object
Dim mFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim mMemoryStream As New System.IO.MemoryStream
mFormatter.Serialize(mMemoryStream, obj)
mMemoryStream.Position = 0
Return mFormatter.Deserialize(mMemoryStream)
End Function
Public Shared Sub Save(ByVal filename As String, ByVal formattype As FormatType, ByVal obj As Object)
Select Case formattype
Case formattype.Binary
SaveSerializerFile(filename, New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter, obj)
Case formattype.Soap
SaveSerializerFile(filename, New System.Runtime.Serialization.Formatters.Soap.SoapFormatter, obj)
Case formattype.Xml
SaveXmlFile(filename, obj)
End Select
End Sub
Public Shared Function Load(ByVal filename As String, ByVal formattype As FormatType, ByVal XmlFormatObjType As Type) As Object
Select Case formattype
Case formattype.Binary
Return LoadDeSerializeFile(filename, New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)
Case formattype.Soap
Return LoadDeSerializeFile(filename, New System.Runtime.Serialization.Formatters.Soap.SoapFormatter)
Case formattype.Xml
Return LoadXmlFile(filename, XmlFormatObjType)
End Select
Return Nothing
End Function
Public Enum FormatType
Xml
Binary
Soap
End Enum
End Class
类的一个实例就是一项数据,如果有多个配置可选或者有多项数据,那就是一个数据集合了。在保存配置时,其实是将数据集合保存到文件里去。所以这里用集合的概念来处理。
为了使处理简单些,我引进一个接口,要求每个配置类或数据类必需实现这个接口。
Public Interface IConfigInformation
Property Name() As String
End Interface
Property Name() As String
End Interface
NAME其实是字典键值。
处理的基类:
Public MustInherit Class ConfigInformationCollectionBase(Of TConfigInformation As IConfigInformation)
Inherits System.Collections.DictionaryBase
Private gformattype As SerializeHelper.FormatType = SerializeHelper.FormatType.Binary
Private gFileName As String = AppDomain.CurrentDomain.BaseDirectory & "{0}.dat" '{0}默认取类名,{1},文件后缀,这里默认都取为dat
Public Sub Add(ByVal item As TConfigInformation)
If Not Me.Dictionary.Contains(item.Name) Then Me.Dictionary.Add(item.Name, item)
End Sub
Public Sub Remove(ByVal Name As String)
If Me.Dictionary.Contains(Name) Then Me.Dictionary.Remove(Name)
End Sub
Public ReadOnly Property Items() As TConfigInformation()
Get
Dim tmp(Me.Count - 1) As TConfigInformation
Me.Dictionary.Values.CopyTo(tmp, 0)
Return tmp
End Get
End Property
Public ReadOnly Property Names() As String()
Get
Dim tmp(Me.Count - 1) As String
Me.Dictionary.Keys.CopyTo(tmp, 0)
Return tmp
End Get
End Property
Public Overloads Sub Clear()
Me.Dictionary.Clear()
End Sub
Default Public ReadOnly Property Item(ByVal Name As String) As TConfigInformation
Get
Return CType(Me.Dictionary.Item(Name), TConfigInformation)
End Get
End Property
Public Sub Save()
Dim mItems(Me.Count - 1) As TConfigInformation
Me.InnerHashtable.Values.CopyTo(mItems, 0)
SerializeHelper.Save(gFileName, gformattype, mItems)
End Sub
Private Sub Load()
If Not IO.File.Exists(gFileName) Then
Initialize()
Save()
Else
Dim mItems() As TConfigInformation
mItems = CType(SerializeHelper.Load(gFileName, gformattype, GetType(TConfigInformation)), TConfigInformation())
For Each item As TConfigInformation In mItems
Me.Add(item)
Next
End If
End Sub
'继承时,若有初始赋值,在此实现
Public MustOverride Sub Initialize()
'默认为FormatType.Binary
Sub New()
gFileName = String.Format(gFileName, GetType(TConfigInformation).Name)
Me.Load()
End Sub
Sub New(ByVal formattype As SerializeHelper.FormatType)
gFileName = String.Format(gFileName, GetType(TConfigInformation).Name)
gformattype = formattype
Me.Load()
End Sub
Sub New(ByVal file As String, ByVal formattype As SerializeHelper.FormatType)
gFileName = file
gformattype = formattype
Me.Load()
End Sub
End Class
使用举例:
1、定义配置或数据类
<Serializable()> _
Public Class MyConfigInfo
Implements IConfigInformation
Private mMachine As String
Private mLogins(-1) As Login
Public Property Machine() As String Implements IConfigInformation.Name
Get
Return mMachine
End Get
Set(ByVal value As String)
mMachine = value
End Set
End Property
Public ReadOnly Property Logins() As Login()
Get
Return mLogins
End Get
End Property
Public Sub Add(ByVal login As Login)
ReDim Preserve mLogins(mLogins.Length)
mLogins(mLogins.Length - 1) = login
End Sub
<Serializable()> _
Public Class Login
Private mUser As String
Private mPass As String
Public Property User() As String
Get
Return mUser
End Get
Set(ByVal value As String)
mUser = value
End Set
End Property
Public Property Pass() As String
Get
Return mPass
End Get
Set(ByVal value As String)
mPass = value
End Set
End Property
Sub New()
End Sub
Sub New(ByVal user As String, ByVal pass As String)
Me.User = user
Me.Pass = pass
End Sub
End Class
End Class
Public Class MyConfigInfo
Implements IConfigInformation
Private mMachine As String
Private mLogins(-1) As Login
Public Property Machine() As String Implements IConfigInformation.Name
Get
Return mMachine
End Get
Set(ByVal value As String)
mMachine = value
End Set
End Property
Public ReadOnly Property Logins() As Login()
Get
Return mLogins
End Get
End Property
Public Sub Add(ByVal login As Login)
ReDim Preserve mLogins(mLogins.Length)
mLogins(mLogins.Length - 1) = login
End Sub
<Serializable()> _
Public Class Login
Private mUser As String
Private mPass As String
Public Property User() As String
Get
Return mUser
End Get
Set(ByVal value As String)
mUser = value
End Set
End Property
Public Property Pass() As String
Get
Return mPass
End Get
Set(ByVal value As String)
mPass = value
End Set
End Property
Sub New()
End Sub
Sub New(ByVal user As String, ByVal pass As String)
Me.User = user
Me.Pass = pass
End Sub
End Class
End Class
2、实现处理
Public Class ConfigData
Inherits ConfigInformationCollectionBase(Of MyConfigInfo)
Sub New()
MyBase.New()
End Sub
Sub New(ByVal formattype As SerializeHelper.FormatType)
MyBase.New(formattype)
End Sub
Sub New(ByVal file As String, ByVal formattype As SerializeHelper.FormatType)
MyBase.New(file, formattype)
End Sub
'这是默认值,如果没有数据文件则生成文件并同时添加这些数据;若已存在文件,这里略去,不会处理。
Public Overrides Sub Initialize()
Dim item As MyConfigInfo
item = New MyConfigInfo
With item
.Machine = "Fk-A01-02"
.Add(New MyConfigInfo.Login("LzmTW", "001"))
.Add(New MyConfigInfo.Login("Lzm", "002"))
End With
Me.Add(item)
item = New MyConfigInfo
With item
.Machine = "Fk-A01-03"
.Add(New MyConfigInfo.Login("L", "003"))
.Add(New MyConfigInfo.Login("Lz", "004"))
.Add(New MyConfigInfo.Login("LzmTW", "001"))
End With
Me.Add(item)
End Sub
End Class
测试:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim test As New ConfigData
Console.WriteLine(test.Item("Fk-A01-03").Logins(0).User) 'L
test.Item("Fk-A01-03").Logins(0).User = "Hello"
test.Save() '存盘
'用另一个打开,看看
Dim test2 As New ConfigData
Console.WriteLine(test2.Item("Fk-A01-03").Logins(0).User) 'Hello
End Sub
Dim test As New ConfigData
Console.WriteLine(test.Item("Fk-A01-03").Logins(0).User) 'L
test.Item("Fk-A01-03").Logins(0).User = "Hello"
test.Save() '存盘
'用另一个打开,看看
Dim test2 As New ConfigData
Console.WriteLine(test2.Item("Fk-A01-03").Logins(0).User) 'Hello
End Sub