Author:水如烟
配置类或数据类都需要可序列化。通常,序列化有三种方式,序列化和反序列化的过程可以做成一个静态类,如下:
Public Class SerializeHelperClass SerializeHelper Private Sub New()Sub New() End Sub Private Shared Function GetXML()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()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()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()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()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()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()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()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()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 FormatTypeEnum FormatType Xml Binary Soap End EnumEnd Class类的一个实例就是一项数据,如果有多个配置可选或者有多项数据,那就是一个数据集合了。在保存配置时,其实是将数据集合保存到文件里去。所以这里用集合的概念来处理。
为了使处理简单些,我引进一个接口,要求每个配置类或数据类必需实现这个接口。
Public Interface IConfigInformationInterface IConfigInformation Property Name()Property Name() As StringEnd InterfaceNAME其实是字典键值。
处理的基类:
Public MustInherit Class ConfigInformationCollectionBaseClass 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()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()Sub Remove(ByVal Name As String) If Me.Dictionary.Contains(Name) Then Me.Dictionary.Remove(Name) End Sub Public ReadOnly Property Items()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()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()Sub Clear() Me.Dictionary.Clear() End Sub Default Public ReadOnly Property Item()Property Item(ByVal Name As String) As TConfigInformation Get Return CType(Me.Dictionary.Item(Name), TConfigInformation) End Get End Property Public Sub Save()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()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()Sub Initialize() '默认为FormatType.Binary Sub New()Sub New() gFileName = String.Format(gFileName, GetType(TConfigInformation).Name) Me.Load() End Sub Sub New()Sub New(ByVal formattype As SerializeHelper.FormatType) gFileName = String.Format(gFileName, GetType(TConfigInformation).Name) gformattype = formattype Me.Load() End Sub Sub New()Sub New(ByVal file As String, ByVal formattype As SerializeHelper.FormatType) gFileName = file gformattype = formattype Me.Load() End SubEnd Class使用举例:
1、定义配置或数据类
<Serializable()> _Public Class MyConfigInfoClass MyConfigInfo Implements IConfigInformation Private mMachine As String Private mLogins(-1) As Login Public Property Machine()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()Property Logins() As Login() Get Return mLogins End Get End Property Public Sub Add()Sub Add(ByVal login As Login) ReDim Preserve mLogins(mLogins.Length) mLogins(mLogins.Length - 1) = login End Sub <Serializable()> _ Public Class LoginClass Login Private mUser As String Private mPass As String Public Property User()Property User() As String Get Return mUser End Get Set(ByVal value As String) mUser = value End Set End Property Public Property Pass()Property Pass() As String Get Return mPass End Get Set(ByVal value As String) mPass = value End Set End Property Sub New()Sub New() End Sub Sub New()Sub New(ByVal user As String, ByVal pass As String) Me.User = user Me.Pass = pass End Sub End ClassEnd Class2、实现处理
Public Class ConfigDataClass ConfigData Inherits ConfigInformationCollectionBase(Of MyConfigInfo) Sub New()Sub New() MyBase.New() End Sub Sub New()Sub New(ByVal formattype As SerializeHelper.FormatType) MyBase.New(formattype) End Sub Sub New()Sub New(ByVal file As String, ByVal formattype As SerializeHelper.FormatType) MyBase.New(file, formattype) End Sub '这是默认值,如果没有数据文件则生成文件并同时添加这些数据;若已存在文件,这里略去,不会处理。 Public Overrides Sub Initialize()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 SubEnd Class测试:
Private Sub Button3_Click()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