AllExperts > Experts 
Search      

VB.NET

Volunteer
Answers to thousands of questions
 Home · More Questions · Answer Library  · Encyclopedia ·
More VB.NET Answers
Question Library

Ask a question about VB.NET
Volunteer
Experts of the Month
Expert Login

Awards

About Us
Tell friends
Link to Us
Disclaimer

 
 
 
 
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?

 
   

You are here:  Experts > Computing/Technology > Basic > VB.NET > Class Serialization

Topic: VB.NET



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.

This should do the trick:

'--[ SerializeTest.vb ]--

Imports System.Xml.Serialization
Imports System.IO

<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")

   objST1.Save("C:\serializetest-1.bin")
   objST2.Save("C:\serializetest-2.bin")

   Dim objST3 As SerializeTest = SerializeTest.Load("C:\serializetest-1.bin")
   Dim objST4 As SerializeTest = SerializeTest.Load("C:\serializetest-2.bin")

   TextBox1.Text = "ST3: " & objST3.MyID & " - " & objST3.MyData & ControlChars.CrLf & "ST4: " & objST4.MyID & " - " & objST4.MyData

Hope this helps!

Add to this Answer    Ask a Question



  Rate this Answer
   Was this answer helpful?
Not at allDefinitely              
   12345  

     
About Us | Advertise on This Site | User Agreement | Privacy Policy | Help
Copyright  © 2008 About, Inc. About and About.com are registered trademarks of About, Inc. The About logo is a trademark of About, Inc. All rights reserved.