Reputation: 657
I'm working on a vb.net project where a user can save and open a binary text. However, the problem is that the when opening a file, it returns a object instead of string and integer.
It returns Projectname.Classname What I want it to return is name and age that the user entered when saving the file.
Here is my code:
''' <summary>
''' When the user clicks open
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub OpenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenToolStripMenuItem.Click
Try
If (openFileDialog1.ShowDialog = DialogResult.OK) Then
thefilename = openFileDialog1.FileName
Dim message = animalmgr.ReadFile(thefilename)
'Getting method from manager
If (Not (message) Is Nothing) Then
message.ToList().ForEach(Sub(msg) Resultlst.Items.Add(msg))
Else
UpdateResults()
End If
End If
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error in opening file")
End Try
End Sub
ReadFile function in the manager class:
''' <summary>
''' Reads a file from binary
''' </summary>
''' <param name="filename"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ReadFile(ByVal filename As String) As Animal()
Dim BinSerial As BinSerializerUtility = New BinSerializerUtility
Dim animals = BinSerial.BinaryFileDeSerialize(Of Animal)(filename)
Return animals.ToArray
End Function
I did the exact same project in C# which worked perfectly, I don't know why it doesn't work in vb.net however. Does anyone know the problem and how to solve it?
Update: Class BinSerializerUtility
Public Class BinSerializerUtility
Public Sub BinaryFileSerialize(ByVal objs As List(Of Animal), ByVal filePath As String)
Dim fileStream As FileStream = Nothing
Try
fileStream = New FileStream(filePath, FileMode.Create)
Dim b As BinaryFormatter = New BinaryFormatter
For Each obj In objs
b.Serialize(fileStream, obj)
Next
Finally
If (Not (fileStream) Is Nothing) Then
fileStream.Close()
End If
End Try
End Sub
Public Function BinaryFileDeSerialize(Of T As {Class})(ByVal filePath As String) As List(Of T)
Dim list = New List(Of T)
If Not File.Exists(filePath) Then
Throw New FileNotFoundException(("The file" + " was not found. "), filePath)
End If
Dim fileStream = New FileStream(filePath, FileMode.Open)
Dim b As BinaryFormatter = New BinaryFormatter
While (fileStream.Position < fileStream.Length)
list.Add(CType(b.Deserialize(fileStream), T))
End While
Return list
End Function
End Class
Animal class:
<Serializable()>
Public MustInherit Class Animal
Implements IAnimal
Private theCatagorytype As Categorytype
Private m_name As String
Private m_age As Integer
Private m_gender As String
Private m_id As Integer
Public Sub New(ByVal typ As Categorytype)
MyBase.New()
theCatagorytype = typ
End Sub
Public Sub New()
MyBase.New()
End Sub
#Region "Properties"
Public Overridable ReadOnly Property Description As String
Get
Return String.Format("{0}, {1}, {2}, {3}", Me.Id, Me.Name, Me.Age, Me.Gender)
End Get
End Property
Public Property Categorytype As Categorytype
Get
Return theCatagorytype
End Get
Set(value As Categorytype)
theCatagorytype = value
End Set
End Property
Public Property Id As Integer Implements IAnimal.Id
Get
Return m_id
End Get
Set(value As Integer)
If (value > 0) Then
m_id = value
End If
End Set
End Property
Public Property Name As String Implements IAnimal.Name
Get
Return m_name
End Get
Set(value As String)
m_name = value
End Set
End Property
Public Property Age As Integer
Get
Return m_age
End Get
Set(value As Integer)
m_age = value
End Set
End Property
Public Property Gender As String Implements IAnimal.Gender
Get
Return m_gender
End Get
Set(value As String)
m_gender = value
End Set
End Property
#End Region
Public MustOverride Function GetEaterType() As EaterType Implements IAnimal.GetEaterType
Public MustOverride Function GetSpecies() As String Implements IAnimal.GetSpecies
End Class
Upvotes: 2
Views: 703
Reputation: 38875
Rather than writing a class wrapper for an operation, I think it makes more sense to put such Save
and Load
functions in the class itself:
' in Animal class:
Friend Shared Function LoadData(myFile As String) As List(Of Animal)
Dim newList As List(Of Animal)
If File.Exists(myFile) Then
Using fs As New FileStream(myFile, FileMode.Open)
Dim bf = New BinaryFormatter
newList = CType(bf.Deserialize(fs), List(Of Animal))
End Using
Else
'return empty list of there is no file
newList = New List(Of Animal)
End If
Return newList
End Function
This seems simpler than trying to read one object at a time and place it in a List. Organizationally, it makes for fewer utility classes if the Foo
s, Bar
s and Animal
s can all serialize and deserialize themselves. To load them:
animals = Animal.LoadData(FileName)
' put animals in a ListBox:
myfrm.ListBox1.Items.AddRange(animals.ToArray)
Even better than making a copy of the animals for the list box, is to use your List(Of Animal)
as the DataSource
. That way, the user sees the same data set as your code is using.
Upvotes: 1
Reputation: 40393
When adding objects to a listbox or dropdown list, by default it uses ToString()
to give you a string representation of the object, and the class name is the default ToString()
implementation.
If you override ToString()
in your Animal
class, it will display however you need it to.
EDIT This is assuming you really want your ReadFile
method to return a collection of Animal
objects, and you want to add the actual objects to the listbox instead of truly adding string representations to the listbox.
Upvotes: 0