John.P
John.P

Reputation: 657

Returning object instead of string and integer

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

Answers (2)

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 Foos, Bars and Animals 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

Joe Enos
Joe Enos

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

Related Questions