Tag Archives: vb.net

Sorting by IComparable vs IComparer

29 Jun

These are two interfaces that used to confuse me. I didn’t know when to use one or when to use the other. The aim of this post is to make it easier for someone to understand the differences and choose appropriately.

In as a few words as possible:
i)A class that implements IComparable can be sorted or compared to another class instance in a manner that you define.

ii)A class that implements IComparer can be used to sort or compare classes that do or do not implement IComparable.

The List.Sort() Method.

Every list(generic list, array, arraylist) has a built-in method called Sort(). The Sort() method knows how to sort all objects that implement the IComparable interface. The method uses an object’s CompareTo() method to compare it with other objects and use its return value to figure out which object comes first.

To sort objects that do not implement IComparable, you have the IComparer Interface. It’s used to assist the list’s Sort() method in sorting its members.

IComparable.
You implement this within the class you want to be sorted. The interface has only one method called CompareTo() that takes an object as a parameter, compares it with the class and returns an integer value that figures out which object comes first.

See the sample class below.

Public Class Person
    Implements IComparable(Of Person)
    'these should be properties
    Public FirstName As String
    Public LastName As String
    Public Age As Integer

    Public Sub New(ByVal first As String, ByVal last As String, ByVal age As Integer)
        Me.FirstName = first
        Me.LastName = last
        Me.Age = age
    End Sub

    Public Function fullName() As String
        Return Me.FirstName & " " & Me.LastName & ": Age - " & Me.Age
    End Function

    Public Function CompareTo(ByVal other As Person) As Integer Implements System.IComparable(Of Person).CompareTo
        If Me.Age > other.Age Then
            Return 1
        ElseIf Me.Age < other.Age Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

Notice the CompareTo() method. It takes another Person class as a parameter, compares the Ages and returns a number indicating
which one comes first. In this method you can create any sorting logic that you need.
You could for example compare by Age, FirstName or Lastname. In this sample the classes will be sorted by Age.

Implementation:
One you have a list of objects that implement IComparable, all you have to do to sort them is just call the List.Sort() method without
passing any parameters. See sample code for a button bellow.

Dim list As List(Of Person)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        list = New List(Of Person)
        list.Add(New Person("Nick", "Masao", 27))
        list.Add(New Person("Sydney", "Mtaita", 3))
        list.Add(New Person("Ruth", "Mtaita", 23))

        Debug.WriteLine("")
        Debug.WriteLine("Unsorted:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

'Just call the sort method without passing any parameters and you are done
‘The Sort() method uses the logic in the CompareTo() method in the class to ‘sort the list members

        list.Sort()

        Debug.WriteLine("")
        Debug.WriteLine("Sorted by Age:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next
End Sub

The code produces the following output.
IComparable_Output
As you can see the objects were sorted by age.

IComparer.

Implement this in a class that you will use to sort other classes that may or may not implement IComparable. This class will be a ‘comparer’ and will impose the sorting order in the List.Sort() method. The interface has only one method called Compare() that takes two objects and returns a value which determines which object comes first.

To sort a list using IComparer, you need to create a new instance of the class that implements it and pass that instance to the List.Sort() method. The list object will then use the class’s Compare() method to sort the members.

Say for example you have a person class with the following definition.  Note that it doesn’t implement any interface.

Public Class Person
    'these should be properties
    Public FirstName As String
    Public LastName As String
    Public Age As Integer

    Public Sub New(ByVal first As String, ByVal last As String, ByVal age As Integer)
        Me.FirstName = first
        Me.LastName = last
        Me.Age = age
    End Sub

    Public Function fullName() As String
        Return Me.FirstName & " " & Me.LastName & ": Age - " & Me.Age
    End Function
End Class

Now to use IComparer to sort a list of objects like the above, you need to create a simple class that implements IComparer and define the sorting manner, like so.

Public Class PersonComparer_ByAge
    Implements IComparer(Of Person)

    Public Function Compare(ByVal x As Person, ByVal y As Person) As Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
        If x.Age > y.Age Then
            Return 1
        ElseIf x.Age < y.Age Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

The Class sorts the Person objects by Age. You could also sort by FirstName or LastName. The only limitation of
IComparer is that it has access to public members of the class only.

See another class that implements IComparer but this time sorts by the FirstName field.

Public Class PersonComparer_ByFistName
    Implements IComparer(Of Person)

    Public Function Compare(ByVal x As Person, ByVal y As Person) As Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
        If x.FirstName > y.FirstName Then
            Return 1
        ElseIf x.FirstName < y.FirstName Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

Implementation:
If you have a list of objects, and you have a class that implements IComparer and has the sorting criteria like
the above class then you have to do the following to sort your list.

  1. Create an instance of your sorting class.
  2. Pass that instance to the list.sort() method.
  3. That’s it.

Sample button code that implements the code above.

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        list = New List(Of Person)
        list.Add(New Person("Nick", "Masao", 27))
        list.Add(New Person("Sydney", "Mtaita", 3))
        list.Add(New Person("Ruth", "Mtaita", 23))

        Debug.WriteLine("Unsorted:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

        Debug.WriteLine("")

'instantiate the sorter/comparer class that implements IComparer

        Dim sortName As New PersonComparer_ByFistName

'pass it as criteria to the sort method

        list.Sort(sortName)

        Debug.WriteLine("Sorted by Firstname:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

        Debug.WriteLine("")
'instantiate the comparer class and pass it to the sort method
        Dim sortAge As New PersonComparer_ByAge
        list.Sort(sortAge)

        Debug.WriteLine("Sorted by Age:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next
    End Sub

The above code produces the following output.

IComparer_Output

Advantages & Limitations.

The advantage of IComparable is that you have access to the private members. i.e you can create your sorting criteria using private members in the class since the CompareTo() method is withing the class. The limitation is you only have that one way of sorting.

The limitation of IComparer is that the object that implements it doesn’t have access to private members of the objects it sorts. It only has access to public members.

Its advantages are, as seen in the sample code above, you can create a number of sorting options, and you have the option of passing the more specific and more appropriate sorting criteria to the Sort() method.

This post is getting too long  and I think I’ll end it here. Hopefully it was an eye opened of some sorts. Till next time, yours truly.

Create a Visual Basic Dynamic-Link Library(dll) from the command line.

28 Apr

A Dynamic-Link Library is a non executable program made of one or more files, which contains classes, procedures, and/or other resources that other programs can use.  Because it is not an executable, it doesn’t need an entry point or the main() procedure  and it usually ends with .dll

Well, you can read more about Dynamic link libraries(dlls) on msdn or wikipedia.

In this post I’ll show you how to create a VB.Net DLL from the command line.

First you need to set up your system to use the vbc compiler. If you do not know how to do this, please read my previous post here.  So from now on I’ll assume you have set up your compiler and we are ready to go.

Steps:

  • Open notepad,  create a class, call it Person and save it as a VB file (Person.vb) . For this post we’ll create a simple Person class.  See the code for the class at the end of the post below.

>>CodeListing No.1 – The Person Class

  • Create a new folder in your main drive (in my case C:\) and call it PersonLibrary.  Save the above class in this folder.
  • Click Start > Run > type cmd  and click OK to open the command prompt.
  • Change to the PersonLibrary directory as shown in the image below.

changedirectory

How to Create a Dynamic-Link Library from the command line.

  1. There are two options. The first one is you create a library that has the same name as the source file.
  • To create a Dll that has the same name as the source file, at the command prompt type the following command.

vbc /target:library Person.vb

  • The command is vbc /target:library nameOfSourceFile.vb notice the space after vbc and the other space after library. Make sure you include them.
  • Browse to the PersonLibrary folder and you’ll see that the Person.dll dynamic-link library has been created. See the image below.

personlibrary1

2.  The other option is that you can provide your own name for the library.

  • To create a Dll that has your own desired name, at the command prompt type the following command.

vbc /target:library /out:PersonLibrary.dll Person.vb

  • The command is vbc /target:library /out:DesiredNameOfLibrary.dll nameOfSourceFile.vb
  • Now browse to the PersonLibrary folder and you’ll see the newly created dll with our custom name PersonLibrary.dll, as well as the old one, Person.dll

personlibrary2

And thats all there is to it. You are done and you have your libraries and you can distribute them now or use them from an application.

How to use the Library.

Before you use the library you simply have to import it into your project and add it as a reference using the command line when compiling.

  • Open Notepad and type in the following code
Imports System
Imports PersonLibrary

Module MainModule
    Sub Main()
        Dim p As New Person("Mike F", "Masao")
        p.Addresses(0) = "6032, Olacity, Arusha"
        p.Addresses(1) = "Tanzania"
        p.Citizenship = "Tanzanian"
        p.BirthDate = #8/21/1982#

        Console.WriteLine("Full Name: " & p.FullName("Mr."))
        Console.WriteLine("Address1: " & p.Addresses(0))
        Console.WriteLine("Address2: " & p.Addresses(1))
        Console.WriteLine("Citizenship: " & p.Citizenship)
        Console.WriteLine("Age: " & p.Age)

        Console.Read()
    End Sub

End Module
  • Save the file as MainProgram.vb under our PersonLibrary folder.
  • Now go back to the command prompt and issue the following command, which will add the library as a reference to the project and then compile the MainProgram code to an executable.

vbc /reference:PersonLibrary.dll MainProgram.vb

  • The command is vbc /reference:NameOfLibrary.dll NameOfMainProgram.vb
  • After the above steps, browse again to the PersonLibrary folder and you’ll see your libraries and your MainProgram.exe executable file as seen in the image below.

aftercompiling

  • Now double click the MainProgram.exe file and you should see the following output on your screen.

output

And we are done.

So now you can create your own libraries by using just notepad and the command prompt.

Hope this was helpful. Till next time, yours truly.

CodeListing No.1  – The Person Class

Public Class Person
    'Fields
    Public FirstName As String
    Public LastName As String
    Public m_BirthDate As Date
    'You can define up to 4 addresses for this person
    Public m_Addresses(3) As String
    Public Citizenship As String = ""

    Sub New(ByVal firstname As String, ByVal lastname As String)
        Me.FirstName = firstname
        Me.LastName = lastname
    End Sub
    Public Property BirthDate() As Date
        Get
            Return m_BirthDate
        End Get
        Set(ByVal value As Date)
            m_BirthDate = value
        End Set
    End Property

    Function FullName(Optional ByVal title As String = "") As String
        FullName = ""
        'use the title if provided
        If title <> "" Then FullName = title & " "
        'append first and last names
        FullName &= FirstName & " " & LastName
    End Function

    'Age is a ReadOnly property
    Public ReadOnly Property Age() As Integer
        Get
            Return Year(Now) - Year(m_BirthDate)
        End Get
    End Property

    Public Property Addresses(ByVal index As Integer) As String
        Get
            If index < 0 Or index > UBound(m_Addresses) Then
                Throw New IndexOutOfRangeException("Invalid address Index")
            End If
            Return m_Addresses(index)
        End Get
        Set(ByVal value As String)
            If index < 0 Or index > UBound(m_Addresses) Then
                Throw New IndexOutOfRangeException("Invalid address Index")
            End If
            m_Addresses(index) = value
        End Set
    End Property

End Class

Using the Timer object and Event Handlers to automatically control actions.

23 Apr

I know I haven’t been able to write for a long time now, and I’ll still be lagging up, but hopefully soon I’ll be back, with full speed, bringing you a new post every week.

Today I’ll show you how to use the System.Windows.Forms.Timer to control when to perform some action or call some procedures. A good example is when you maybe need to send a report to your boss,  say every day at 4pm.timers

In this case, you need a timer object, that calls an event handler which checks the time against your system time to see if it is 4pm or after and then call the procedure that sends the report. Let’s see how you can go about, doing that.

What we need.

  1. A Timer object.
  2. A method to serve as an event handler
  3. Your custom method that does whatever work you want done when it’s time.

We’ll make use of the AddHandler statement to hook up the Timer’s Tick event with our event handler. The AddHandler statement is used to associate an event with an event handler at run time.

See the full code below.

Imports System

Module Sample

Public Class Test

Private Shared myTimer As New System.Windows.Forms.Timer()

Public Shared Sub Main

	'hook up the event to the handler method

        AddHandler myTimer.Tick, AddressOf CheckTime

        ' Sets the timer interval to 1 second and start it.

        myTimer.Interval = 1000

        myTimer.Start()

	MsgBox("The timer is running now....")

	Console.Read()
   RemoveHandler myTimer.Tick, AddressOf CheckTime

End Sub

Public Shared Sub CheckTime(ByVal sender As System.Object, ByVal e As System.EventArgs)

        If DateTime.Parse(DateTime.Now.ToShortTimeString) > DateTime.Parse("11:00 AM") Then

            MsgBox("The time is : " & DateTime.Now.ToShortTimeString)

            'Call SendPendingInvoices()

        End If

    End Sub

End Class
End Module

As you can see above, we created a new Timer object, and in our main procedure, or start up procedure, we hooked up the Timer.Tick event to our CheckTime event handler method, so that it gets called every time the tick event of the timer is fired.  In our case that will be every 1 second.

To test the code, create a new blank console project and copy and paste the code above and simply click run. If your system time is greater than 11:00 AM then you should see a message box pop up every second showing you the current time from your system.

Hope this was helpful.

Till next time, yours truly.

A method for searching a ListView

1 Apr

Here is a simple method that will search a ListView and its subitems and select or highlight the ListViewItem or SubItem that begins with  the search criteria.

In this sample I make use of the ListView.FindItemWithText method which takes three parameters, the first a string specifying the item to find, second a boolen value to specify whether the subitems should be included and the third, the starting index in the listview items collection.

This is how the method works.

  1. The method takes two parameters, first the name of the ListView, and second the text to find.
  2. It starts the search at the first item and goes on until it finds a match. The found ListViewItem is then highlighted.
  3. If you click search again, its starts at the index of the last item and continues until it finds another match.
  4. If no match is found and you click search again, it starts from the beggining, at the first item’s index.

Using the code.

Create a listview object, load it with items and subitems. On your form, outside the method, create these 2 variables:

  • lastSearch, String - This will save your previous search text and compare it with the current text when you call the method again.
  • lastIndex - Integer – Set it to -1. - This will save the index of the found item so that the method starts from here when called again.

After this, call the method and pass the name of the listview you want to search and the text to find.

Here is the full code. You can use it as is, or you can modify it and add some changes as you see fit.

    Private lastSearch As String = ""
    Private lastIndex As Integer = -1

Private Sub SearchListView(ByVal listView As ListView, ByVal txtFind As String)

        Dim foundItem As ListViewItem = Nothing

        If lastSearch = txtFind Then
            If lastIndex < listView.Items.Count - 1 Then
                foundItem = listView.FindItemWithText(txtFind, True, lastIndex + 1)
            Else
                foundItem = listView.FindItemWithText(txtFind, True, 0)
            End If
        Else
            foundItem = listView.FindItemWithText(txtFind, True, 0)
        End If
        lastSearch = txtFind
        lastIndex = -1
        If Not (foundItem Is Nothing) Then
            lastIndex = foundItem.Index
            listView.Focus()
            listView.Items(foundItem.Index).Selected = True
        End If
    End Sub

I wrote this in .Net 2.0 but it should work with 3.0 and 3.5. The method is not perfect, its just an eye opener and the rest is up to the user to dig and improvise.

Till next time, yours truly.

Parameters order in ADO.Net command objects.

13 Mar

I didn’t know that the order of parameters in a SQl statement mattered. At least when using MS Access as your back-end. Untill recently when I wrote the function below that updates an MS Access  2003 Database.

Public Function Update() As Integer
           Using cn As New OleDbConnection(ConnectionString)
            Dim sql As String = "UPDATE SupplyItem SET Balance = @Balance " & _
                                       "WHERE ProductID = @ProductID AND UnitID = @UnitID;"

            Dim cmd As OleDbCommand = New OleDbCommand
            cmd.Connection = cn
            cmd.CommandType = CommandType.Text
            cmd.CommandText = sql
            cmd.Parameters.AddWithValue("@UnitID", Me.UnitID)
            cmd.Parameters.AddWithValue("@Balance", Me.Balance)
            cmd.Parameters.AddWithValue("@ProductID", Me.ProductID)
            cn.Open()
            Dim res As Integer = cmd.ExecuteNonQuery
            cn.Close()
            Return res
        End Using

    End Function

I ran a unit test on the function and the test was failing. I tried again and again and it failed with some parameter error or something. I checked and rechecked the database, the parameters and everything. But it was still failing.

I got confused. You see, I thought that because the parameters are named, then it doesn’t matter in which order you suppply them to the command object. As long as you supply all the parameters and values, the query should work. Is it different for SQL server and for MS Access? or it doesn’t matter at all and maybe my system had other problems? I’m not sure.

So after a while and after trying everything else, I decided to change the order of the parameters to this.

            cmd.Parameters.AddWithValue("@Balance", Me.Balance)
            cmd.Parameters.AddWithValue("@ProductID", Me.ProductID)
            cmd.Parameters.AddWithValue("@UnitID", Me.UnitID)

And voila! It worked like magic. I was confused even more.

But I guess the more you write code, the more you discover little things that you overlooked before or didn’t bother to go into the details at an earlier time.

Till next time, yours truly.

Add Support for Automatic release of resources in your Classes

11 Feb

This is the part two to my previous topic, where I discussed the .Net Using Statement and showed just a tip on how to implement it.

This time we’ll see how to add support for handling of Unmanaged Resources in your components, simply by Implementing  the IDisposable interface and its Dispose method in your specific component.

How to add support for Unmanaged Resources

I’m going to create a simple class and call it EventLogger. In the class we will use a Filestream and a StreamWritter to write to a physical text file, and we will add support for automatic handling of the unmanaged resources whenever the class is called.

Steps.

  1. Add the IDisposable interface to the class
  2. Add the IDisposable.Dispose method to the class
  3. In the Dispose method, call the FileStream and the StreamWritter’s dispose methods.
  4. When calling the class use the Using Statement.

See the full code below.

Imports System
Imports System.Text
Imports System.IO

Public Class EventLogger
    Implements IDisposable

    Private logFileName As String = "AppLog.txt"
    Private logFile As FileStream = Nothing
    Private sw As StreamWriter = Nothing

    'Initializes a new instance of
    'the class.
    Public Sub New()
        MyBase.New()
        logFile = File.Open(logFileName, FileMode.Append)
        sw = New StreamWriter(logFile)
    End Sub

    ' Adds the specified message to the log.
    Public Sub Add(ByVal message As String)
        sw.WriteLine(message)
    End Sub

    ''' <summary>
    ''' Implements the Dispose() method of the
    ''' IDisposable interface to do application-defined
    ''' tasks like freeing,releasing or resetting of unmanaged
    ''' resources.
    ''' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        sw.Dispose()
        logFile.Dispose()
    End Sub

End Class

Simple as that. Now lets see a sample on how to call the class.
In your main procedure implement the using statement to call the class like so.

Module Module1

    Sub Main()

Using mylog As New EventLogger
            mylog.Add(DateTime.Now.ToString & ": What is happening here")
            mylog.Add(DateTime.Now.ToString & ": Yet another message coming in")
        End Using
    End Sub

End Module

Well, this is just one way to kill a bird. You could it in a hundred other ways.

Like for example you could get rid of the Unmanaged resources in the Add method by implementing the Using statement with the StreamWriter,and then in your main method you create a new instance of the class and call the Add method.

But that would be a lot more code. I think this way is safe and leads to less and more readable code.

Hope this was helpful, till next time, yours truly.

For vs For Each loops – Performance Issues.

26 Jan

I’m sure one of you has come to a point where they thought, should I use a For loop or a For Each loop? And issues like which one is faster or which one is more effective usually arise. Well,  a real developer should be thinking like “I can measure this.”, which is what I’m going to do here today.

The speed of a For or For Each loop usually depends on the number of items in the list, the type of list ( array, arraylist, generic list, dictionary) etc.

I wrote this peace of code here (VB.Net) and used an arraylist and a generic list, both filled with integers from 0 to 1000 and measured the speed of writting all the numbers to the console window using For and For Each loops.

Imports System.Diagnostics
Module Sample

    Sub Main()
        'Dim list As New ArrayList
        Dim list As New List(Of Integer)
        For i As Integer = 0 To 1000
            list.Add(i)
        Next

        'Timer starts here
        Dim t As New Stopwatch
        t.Start()

        For Each i As Integer In list
            Console.WriteLine(i.ToString)
        Next

        ' For i As Integer = 0 To list.Count - 1
        'Console.WriteLine(list(i).ToString)
        'Next

        t.Stop()
        Console.WriteLine("LOOP time: " & t.ElapsedMilliseconds)

        Console.Read()
    End Sub

End Module

Remove the comments appropriately if you are going to test it.

On my machine I got these statistics in milliseconds.

loops

Now, these results does not necesarly mean that generic lists are slower than arraylists or For Each loops are slower than For loops. That is not the point of this post at all.

The point is just simple. You should learn to put your concerns to the test. So I welcome you to test your loops and see for yourself which one is better than the other, though personally I never even think about it. I just use the one I think is more appropriate depending on the situation.

Till next time.

Yours truly.

.Net Serialization – Creating a Universal Generic Serialization Class

16 Sep

Introduction.
First things first. Simply put, serialization is the process of saving an object’s instance to disk,  where it can be just stored, transmitted or shared and re-created later to form a clone of the same object, a process known as deserialization. Well I tried with the definition. Wikipedia has a better one.

Serialization is the process of saving an object onto a storage medium (such as a file, or a memory buffer) or to transmit it across a network connection link in binary form. When the resulting series of bytes is reread according to the serialization format, it can be used to create an accurate clone of the original object.

In .Net, serialization is considered one of the advanced topics, well I think it is not that complicated. In this example I will create a class, that has generic methods and functions, that will help you easily serialize and deserialize just about any type of object to and from a disk file.

Consider the following piece of code. Notice the libraries we have used because we will use the same libraries throughout this post and won’t repeat them in every piece of code. So please include them in your project.


Imports System
Imports System.IO
Imports System.Reflection
Imports System.Xml.Serialization
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Runtime.Serialization.Formatters.Soap
Imports System.Security.Permissions
Imports System.Collections

Module Module1
   
        Public Sub SerializeToFile(ByVal path As String, ByVal data As String)
            'open the file stream for output
            Using fs As New FileStream(path, FileMode.Create)
                'create a formatter for this file stream
                Dim bf As New BinaryFormatter(Nothing, _
                New StreamingContext(StreamingContextStates.File))
                'serialize the string and close the stream
                bf.Serialize(fs, data)
            End Using
        End Sub

 Public Function DeserializeFromFile(ByVal path As String) As String
            'open the stream from input
            Using fs As New FileStream(path, FileMode.Open)
                'create a formatter for this file stream
                Dim bf As New BinaryFormatter(Nothing, _
                New StreamingContext(StreamingContextStates.File))

                'deserialize the data from the stream
                Return DirectCast(bf.Deserialize(fs), String)

            End Using
        End Function

Sub Main()
        Dim i As String = "This is a sample string"
       Serializetofile("C:\Test\sample.txt",i)
      Console.Writeline(DeserializeFromFile("C:\Test\sample.txt"))
      Console.Read
End Sub

This is a sample that uses binary serialization to serialize and deserialize a string to a disk file. Problem with this example is that everytime you need to serialize an object, you need to explicitly hard code the type in your method. Like String, Array, Hashtable etc.

So I decided to write a class, that has generic methods serialize and deserialize any type of object. This is why I love generics, because these methods will be type safe, and will save you a lot of repetition.  If you need to serialize like 10 diferent objects, all you have to do is specify the type of object you are serializing, or deserializing. That means instead of writing 10 diferent methods to serialize 10 objects, you write one method that can serialize all of your objects.

I will post the whole piece of code and explain below with samples.


Public Class Serializer

 Public Sub SerializeToFile(Of T)(ByVal path As String, ByVal data As T)
            'open a file stream to save our object in.
            Using fs As New FileStream(path, FileMode.Create)

                'create a formatter for this file stream
                Dim bf As New BinaryFormatter(Nothing, _
                New StreamingContext(StreamingContextStates.File))

                'serialize the object and close the stream
                bf.Serialize(fs, data)

            End Using
        End Sub

        Public Function DeserializeFromFile(Of T)(ByVal path As String) As T
            'open the stream from input path
            Using fs As New FileStream(path, FileMode.Open)

                'create a formatter for this file stream
                Dim bf As New BinaryFormatter(Nothing, _
                New StreamingContext(StreamingContextStates.File))

                'deserialize the object from the stream
                Return DirectCast(bf.Deserialize(fs), T)

            End Using
        End Function

       Public Sub SoapSerialize(Of T)(ByVal path As String, ByVal data As T)
            'create a soap formater
            Dim sf As New SoapFormatter

            'serialize the object to disk in soap format
            Using fs As New FileStream(path, FileMode.Create)
                sf.Serialize(fs, data)
            End Using
        End Sub

        Public Function SoapDeserialize(Of T)(ByVal path As String) As T
            'create a soap formater
            Dim sf As New SoapFormatter

       'deserialize the object from disk
            Using fs As New FileStream(path, FileMode.Open)
                Return DirectCast(sf.Deserialize(fs), T)
            End Using
        End Function

End Class

This class demonstrates BINARY and SOAP serialization. It has four methods, two serialization procedures, one for Binary and the other for SOAP, and two deserialization functions, for Binary and SOAP deserialization. There is also XML serialization, but it’s not included, I will spare that and discuss it in a different post because it has some complications and limitations. Binary serialization is the most robust of these types, the only limitation with this type of serialization is that it’s platform specific, it only works with .Net, while soap and xml works with multiple platforms.

Now we are going to create a simple person class, serialize and deserialize it using the methods in the above class to demonstrate how it works. Copy and paste the folowing  code somewhere within the module.


<serializable()> _
Public Class Person
'these should be properties in a real app.
  Public Name As String
  Public Gender As String
  Public Age As Integer

'the constructor
   Public Sub New(Byval name As string, Byval gender As string, Byval age As Integer)
          me.Name = name
          me.Gender= gender
          me.Age = age
   End sub
End Class

To create a serializable class you simply add the <serializable()> attribute at the beginning of the class. So let us test and run our class in the main procedure. The code is straight forward and explains itself.

In action


Sub Main()
     Dim ser As New Serializer

      Dim i As New Arraylist
 i.add(New person("Nickson Mtaita","Male", 27))
 i.add(New person("Willy Mtaita","Male", 24))
 i.add(New person("Diana Mtaita","Female", 22))

      'SERIALIZE USING THE BINARY SERIALIZER

         ser.SerializeToFile(Of Arraylist)("C:\Test\Sample.txt", i)

      'Declare a new arraylist

   Dim z as New Arraylist 

      'Deserialize from file using the binary deserializer
      'Assign it to our new arraylist

  z = ser.DeserializeFromFile(Of Arraylist)("C:\Test\Sample.txt")
 
      'Add a new person to the new deserialized arraylist of persons

    z.add(new person("Faith Masao","Female", 17))

      'Iterate though the arraylist to display name and gender

 Console.Writeline()
 Console.Writeline("BINARY Deserialized")
 Console.Writeline()

 For Each p As Person In z
  Console.Writeline("{0} - {1}", p.Name, p.Gender)
 Next

     
      'now serialize this new arraylist using the SOAP SERIALIZER

          ser.SoapSerialize(Of Arraylist)("C:\Test\sample.xml", z)

      'Declare a new arraylist

 Dim x As New Arraylist 

      'Deserialize from file using the SOAP deserializer

 x = ser.SoapDeserialize(Of Arraylist)("C:\Test\sample.xml")

 Console.Writeline()
 Console.Writeline("SOAP Deserialized")
 Console.Writeline()

      'Iterate though the newest arraylist to display name and gender
 For Each p As Person In x
  Console.Writeline("{0} - {1}", p.Name, p.Gender)
 Next

 Console.Writeline()
 Console.Write("Press enter to close..")
 Console.Read
End Sub

In windows explorer navigate to the C:\Test directory and notice the new files created there, “Sample.txt” and “Sample.xml”. Open the files and see the contents. The SOAP method serializes object in a readable XML format, which makes it easy for reviewing.

Output

Output

Conclusion
This is sample code, and it lacks a lot of things, but you can optimize it a lot and make it a better working piece of code. For example you should add try catch blocks to catch exceptions, consider using generic lists and dictionaries instead of arraylists to avoid boxing, etc etc.

Serialization is a whole large topic that can not be covered in just a single post like this, but the aim here was to provide you with this simple generic class idea, that you can use to serialize different objects, and save you a lot of lines of repeating code, and some time too.

This was just a scratch at the top. I’ll talk about xml serialization in a different post on a different day. For now…Adios!.

Coding How-to #3: Programmatically find someone’s Age

4 Sep

Today’s post is a short one and you might actually find it useful for some of your projects. In case you want to thank me, I accept cash and credit cards..oh, and paypal too. -:)

So how would you normally find someone’s age as of now, given their birthdate? Easy, right? You just take today’s date minus their birthdate, like so.

Age = Now.Year - BirthDate.Year

 Well this might work fine, but it is not entirely correct. Someone’s age is defined in the number of whole years that has passed since birthdate. So we are gonna make use the VB.Net’s function Date.DayofYear  to calculate the actual age of our individual.

So given the above explanation, this is the full VB.Net code, self explaining so you can easily translate to your language of choice.

Public Function GetAge(ByVal birthdate As Date) As Integer
  Dim Age as Integer
  Age = Now.Year - BirthDate.Year
     If Now.DayOfYear < BirthDate.DayOfYear Then Age -= 1
  Return Age
         End Function

 

 

Works fine. Till next time. Your’s truly.

Coding How-to #2: Find the largest value in an Integer Array

26 Aug

So how do you programmatically get the largest number in an integer array? Well I have two simple ways of doing it – as usual, you can kill a bird with two stones right? or is it the other way round? you can kill two birds with one stone, no wait, you can kill two stones with one bird…you can kill two…..CUT!! anyway, let’s write some code.

Using built in array methods ( Sort and Reverse)

Now this is a dirty trick. Short and concise and gets the work done, though it might have some drawbacks. First I sort the array, it’ll sort the integers from the minimum to the largest. Then I reverse the array and capture the first element. Ahaa!

Private Function GetLargeInt(ByVal data() As Integer) As Integer

      Array.Sort(data)

      Array.Reverse(data)   

      Return data(0)

 End Function

Just try it and see for yourself. Works fine.

Standard way

Now here I wrote a “better” algorithm, that doesn’t rely on the in-built array functions. Get the minimum value for the integer data type (You could actually modify this code to work with the numeric data type you want to) and iterate through the array with a simple for each loop comparing each element with my value. If it is larger than my value, I assign it as my new value and move to the next. Well the code will explain more.

 

Private Function GetLargeInt(ByVal data() As Integer) _
                           As Integer
   Dim res As Integer = Integer.MinValue

   For Each i As Integer In data
      If i>res Then res = i
   Next
 Return res
 End Function

 

You can create a simple console app to try this out. Or you can try it anywhere in your project. I tried it with this array..

Dim arr As Integer() = _
{-1,132,1121,3,15,6,17,8,9,10,12,14,157,75}

 

 Console.Writeline(GetLargeInt(arr).ToString)

..and it returned 1121.

Till next time, I’m out for now.

Follow

Get every new post delivered to your Inbox.