About Chris Expertise I can answer pretty much any question relating to VB.NET and its use in a Windows environment. I specialize in ASP.NET web development and MSSQL database access.
Experience I have over 5 years of industry experience using VB.NET and other .NET technologies for web and database development.
Education/Credentials I have some college education, but does it really matter in this field of work?
Expert: Chris Date: 8/24/2007 Subject: Class Serialization
Question Hi Chris, thanks for your time. Could you give me an example of a serializable class? Here is what I am doing and what I need. I have a Windows app that uses a web service to get data. There are 'Messages' that are pulled from the database by the web service and sent to the application. I want to cache messages so that the app doesn't need to request all records each time it's loaded. So, let's say I have 10 records and my app has already downloaded the first 8. I want to call the web service requestiong only messages with MessageID > 8, so it only returns 9 and 10. These messages are kept in a Message class in the app and these are stored in a class that inherits a generic list collection. When the app shuts down I want to be able to serialize the collection class (an all it's contents) and write this to a flat file. When the application starts I want to be able to read this file in again. Basically I want to keep a copy of all messages previously received. Does this make sense?
All I want is a sample of serialization of a class to a flat file and then de-serialization from the file back into the class? The seialization of a collection would be even better. Here is a sample class you can use. Notice all my properties are readonly. Of my actual class there is only one read/write property and that is a flag indicating whether or not the user has viewed the message.
Public Class SerializeTest
Private mnMyID As Integer
Private msMyData As String
Public Sub New(ByVal vnMyID As Integer, ByVal vsMyData As String)
mnMyID = vnMyID
msMyData = vsMyData
End Sub
Public ReadOnly Property MyID() As Integer
Get
Return mnMyID
End Get
End Property
Public ReadOnly Property MyData() As String
Get
Return msMyData
End Get
End Property
End Class
Answer Serialization has a few catches to it... You need to have a constructor which takes no parameters (this can be marked protected, though), and the member variables you want serialized have to either be marked as public, or have public property accessors backing them that are not marked read-only.
Because you can mark the parameter-less constructor as Protected, you don't have to worry about that change very much. But if you want to keep your read-only properties, you'll have to do a workaround of sorts. A member variable to track whether you're currently de-serializing, set to true in the parameterless constructor, and set false when deserialization is complete should do the trick. Then in your property accessors you want to be read-only, check if this flag is currently true. If it is, proceed to update the value (as part of deserialization), otherwise throw an exception, making that property accessor read-only most of the time. Since this flag will be a protected member, only code within the same class will be able to control it, so we'll have to put the deserialization code within the class itself.
<Serializable()> _
Public Class SerializeTest
Private mnMyID As Integer
Private msMyData As String
Private m_blnDeSerializeMode As Boolean = False
' A parameter-less constructor is required in order to serialize a class
Protected Sub New()
m_blnDeSerializeMode = True
End Sub
Public Sub New(ByVal vnMyID As Integer, ByVal vsMyData As String)
mnMyID = vnMyID
msMyData = vsMyData
End Sub
Public Property MyID() As Integer
Get
Return mnMyID
End Get
Set(ByVal Value As Integer)
If Not m_blnDeSerializeMode Then Throw New Exception("You can not change this paramter.")
mnMyID = Value
End Set
End Property
Public Property MyData() As String
Get
Return msMyData
End Get
Set(ByVal Value As String)
If Not m_blnDeSerializeMode Then Throw New Exception("You can not change this paramter.")
msMyData = Value
End Set
End Property
Public Function Save(ByVal strFilename As String) As Boolean
Try
Dim objSW As New StreamWriter(strFilename, False, System.Text.Encoding.Default)
objSW.Write(Me.Serialize())
objSW.Close()
Return True
Catch ex As Exception
MsgBox("Error serializing to file: " & strFilename & " (" & ex.Message & ")" & ControlChars.CrLf & ControlChars.CrLf & ex.ToString(), MsgBoxStyle.OkOnly, "Serialization Error")
Throw ex
End Try
Return False
End Function
Public Function Serialize() As String
Dim objXS As New XmlSerializer(Me.GetType())
Dim objSW As New StringWriter
objXS.Serialize(objSW, Me)
Return objSW.ToString()
End Function
Public Shared Function Load(ByVal strFilename As String) As SerializeTest
Try
Dim objSR As New StreamReader(strFilename, System.Text.Encoding.Default)
Dim objST As SerializeTest = SerializeTest.DeSerialize(objSR.ReadToEnd())
objSR.Close()
Return objST
Catch ex As Exception
MsgBox("Error deserializing from file: " & strFilename & " (" & ex.Message & ")" & ControlChars.CrLf & ControlChars.CrLf & ex.ToString(), MsgBoxStyle.OkOnly, "Deserialization Error")
Throw ex
End Try
Return Nothing
End Function
Public Shared Function DeSerialize(ByVal strXML As String) As SerializeTest
Dim objXS As New XmlSerializer(GetType(SerializeTest))
Dim objSR As New StringReader(strXML)
Dim objST As SerializeTest = CType(objXS.Deserialize(objSR), SerializeTest)
objST.m_blnDeSerializeMode = False
Return objST
End Function
End Class
'--[ end SerializeTest.vb ]--
Some test code, that'll prove it's serializing and de-serializing properly:
Dim objST1 As New SerializeTest(1, "test1")
Dim objST2 As New SerializeTest(2, "test2")