Posts filed under 'VB.NET Tutorials'

Introduction to Interfaces in VB.NET

Implements IPipeline, IWorker

One problem some programmers new to VB.NET and object oriented programming in general have is understanding interfaces and how they related to classes. In this article, we’ll take an introductory look at interfaces and some of the ways you can use them in your VB.NET applications.

What is an Interface?

To put it in simple terms, an interface is a definition of methods and properties. Sometimes this is referred to as a ‘contract’. If a class agrees to implement an interface it must implement all of the properties and methods defined.

One difference you’ll see in an interface vs. a class is that there is no code, only the templates, aka contracts, for the properties and methods. You’ll also notice that there is no access level defined. It’s always considered public.

Here’s an example interface:

Public Interface IPerson

    Property ID() As Integer

    Property FirstName() As String

    Property LastName() As String

End Interface 

This means that if a class implements the IPerson interface it will have to implement these routines. Here’s an example of a class implementing this interface:

Public Class Customer    Implements IPerson

    Protected _id As Integer
    Protected _firstName As String    Protected _middleName As String
    Protected _lastName As String

    Public Property ID() As Integer Implements IPerson.ID
        Get
            Return _id
        End Get
        Set(ByVal value As Integer)
            _id = value
        End Set
    End Property

    Public Property FirstName() As String Implements IPerson.FirstName
        Get
            Return _firstName
        End Get
        Set(ByVal value As String)
            _firstName = value
        End Set
    End Property
    Public Property MiddleName() As String
        Get
            Return _middleName
        End Get
        Set(ByVal value As String)
            _middleName = value
        End Set
    End Property

    Public Property LastName() As String Implements IPerson.LastName
        Get
            Return _lastName
        End Get
        Set(ByVal value As String)
            _lastName = value
        End Set
    End PropertyEnd Class 

As you can see, each of the properties above, except for MiddleName, has an Implements statement that defines how it will fulfill the Interface contract. The rule is that you can add to the interface inside the implementing class but you can’t take away.

Remember that implementing an interface isn’t the same as creating an instance of a class or creating a subclass. All you’re doing is defining how the external interface should look, not what goes on inside. People do get confused over that point.

Coding Interfaces

Interfaces can be very simple or complex. Most current OOP thought suggests that interfaces be limited to a single method. For example, you might have an IUpdate interface that defines a single Update function and you might have another interface called ICreate that defines a single Create function. You would then combine them into classes that needed to implement them, as in this example:

Public Interface ICreate
    Function CreateNew(ByVal id As Integer) As Boolean
End Interface

Public Interface IUpdate
    Function Update(ByVal id As Integer) As Boolean
End Interface
Public Class Customer
    Implements IPerson, IUpdate, ICreate

As you can see, a class can implement multiple interfaces. Whether it’s better to design with a lot of different interfaces or to group them into logical sections is really up to your own needs. My own take is a bit of a compromise in that I keep them simple with just a few tightly related methods or properties but I don’t religiously limit each interface to a single item.

Another use for interfaces is in defining a common interface for a plug-in architecture as I mentioned in this previous article: How To Create Application Plug-ins In VB.NET. In this case, you will want to have a more complex interface design in most cases since your main app will need a stronger connection to the plug-in.

Do you have any questions about using Interfaces in VB.NET? Please feel free to leave a comment and ask about it.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

29 comments October 23rd, 2007

Introduction to the Comparer Delegate

The Comparer Delegate Does the Hard Work for You

Once you have data in a generic List or Dictionary you may find that you need to sort it into the order you need. This is fairly easy if you’re using simple data types since .NET provides default comparers but it can get a little trickier if you need to sort objects. In this article we’ll look at how to use Comparer Delegates to do this.

What is a Comparer Delegate?

A comparer delegate is a routine that is used to compare two objects. It returns a 1 if the value of the first object is greater, -1 if the value of the first object is lesser, and 0 if the objects are equal. Since we’re working with objects we can compare multiple values in the two objects to determine which is greater than the other.

Code Example #1

In this example we’ll look at sorting PointF coordinates by their distance from 0,0. First, let’s load up our list and call the Sort method with our comparer that we’ll write in a moment.

Dim CoordinateList As New List(Of PointF)(New PointF() {New PointF(14, 22), New PointF(17, 21), _
                                          New PointF(15, 8), New PointF(15, 20), _
                                          New PointF(16, 7), New PointF(15, 21), _
                                          New PointF(17, 7), New PointF(16, 21), _
                                          New PointF(14, 23)})
CoordinateList.Sort(AddressOf ComparePointF)

Now, let’s code our comparer routine, ComparePointF:

Public Function ComparePointF(ByVal positionOne As PointF, ByVal positionTwo As PointF) As Integer
    Dim DistanceOne As Double = Math.Sqrt((positionOne.X ^ 2) + (positionOne.Y ^ 2))
    Dim DistanceTwo As Double = Math.Sqrt((positionTwo.X ^ 2) + (positionTwo.Y ^ 2))
    If DistanceOne > DistanceTwo Then
        Return 1
    ElseIf DistanceOne < DistanceTwo Then
        Return -1
    Else
        Return 0
    End If
End Function

Here we’re using the Pythagorean distance formula to determine the distance from 0,0 for each point and then comparing the results. The List object handles all of the sorting internally so the performance is quite good.

Code Example #2

In this example, we have an invoice object where we’re wanting to sort the objects first by customer type and then by the total amount of the invoice. Here’s what our comparer delegate would look like:

Public Function CompareInvoices(ByVal invoiceOne As Invoice, ByVal invoiceTwo As Invoice) As Integer
    If invoiceOne.CustomerType > invoiceTwo.CustomerType Then
        Return 1
    ElseIf invoiceOne.CustomerType < invoiceTwo.CustomerType Then
        Return -1
    Else
        If invoiceOne.Total > invoiceTwo.Total Then
            Return 1
        ElseIf invoiceOne.Total < invoiceTwo.Total Then
            Return -1
        Else
            Return 0
        End If
    End If
End Function

As you can see in this function, we first compare the customer type, then the total amount. Of course, you could make this even more complex for your sorting situations. All you have to keep in mind is your integer return value.

I hope these examples have been helpful to you in learning how to use the comparer delegate. If you have any further questions or observations about this subject, please feel free to leave a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Add comment October 19th, 2007

How To Create Application Plug-ins In VB.NET

Plugging into an appSooner or later you’ll find that you want to make your application extensible. Perhaps you want to add customer specific processing modules to your backend processes. Maybe you’ll want to offer customers the ability to add their own functionality to your base application. VB.NET and the .NET Framework make this relatively easy to do. Let’s walk through the steps.

Define an Interface

The way to load a .NET assembly dynamically is through reflection. To make this process easier and more controllable within the context of an application I’ve found it best to define a plug-in interface, such as this one:

Public Interface IMyPlugIn

    Function TestFunction(ByVal value As String) As String

    Property MySetting() As String

End Interface

By using the interface this allows us to have a fixed definition for our plug-ins that our main application to work with. This means that we will need less main app code to support our plug-in.

Create A Class

Now we’re ready to create a plug-in class. Here’s the template that gets created:

Public Class CustomerXYZPlugin
    Implements MyPlugIn.IMyPlugIn

    Public Property MySetting() As String Implements MyPlugIn.IMyPlugIn.MySetting
        Get

        End Get
        Set(ByVal value As String)

        End Set
    End Property

    Public Function TestFunction(ByVal value As String) As String Implements MyPlugIn.IMyPlugIn.TestFunction

    End Function

End Class

Now, to complete the plug-in class we will need to add appropriate code it. You can’t define constructors in an interface so you’ll find it best to specify that you’ll either use a parameterless constructor or require that plug-in classes support a specific set of parameters. My preference has been to use parameterless ones and to supply ample properties for the plug-ins.

As for other code, as long as you define the interface you can do just about anything else you want.

Loading The Plug-In

Now we get to the heart of the matter, how to load the plug-in. There are several approaches you can take to this but here’s mine. First, let’s look at the code:

Private Function LoadPlugIn(ByVal LoadPath As String) As MyPlugIn.IMyPlugIn
    Dim NewPlugIn As MyPlugIn.IMyPlugIn
    Try
        Dim PlugInAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom(LoadPath)
        Dim Types() As Type
        Dim FoundInterface As Type
        Types = PlugInAssembly.GetTypes
        For Each PlugInType As Type In Types
            FoundInterface = PlugInType.GetInterface("MyPlugIn.IMyPlugIn")
            If FoundInterface IsNot Nothing Then
                NewPlugIn = DirectCast(PlugInAssembly.CreateInstance(PlugInType.FullName), MyPlugIn.IMyPlugIn)
                Exit For
            End If
        Next
    Catch ex As Exception
        'handle exceptions here
    End Try
    Return NewPlugIn
End Function

As you can see, we’re passing in the path to our plug-in and returning a plug-in interface object from the call. After declaring our return value we enter a try block. I recommend putting this loader logic in an exception handling block since you may be dealing with code that’s outside your direct control.

Next, we create a new Reflection.Assembly object from the file location that was passed into our function and extract the types from it. This allows a plug-in to have functionality beyond just the interface. We search for our interface and, when we find it, create a new instance and exit our search loop. Then we pass back the newly created plug-in object back to our main code.

Here’s a simple example of what the main code might look like:

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim NewPlugIn As MyPlugIn.IMyPlugIn = LoadPlugIn(TextBox1.Text)
    NewPlugIn.MySetting = "Hello World"
    Dim OurTestPlugInValue As String = NewPlugIn.TestFunction("Try It!")
End Sub

Those are the steps to adding a simple plug-in to your application. Of course, there are more things you can do with Reflection and I suggest that you investigate them if you’re thinking about implementing this in one of your apps. Remember that there is a performance penalty for using Reflection and there are security considerations as well so make sure you factor them into your design.

If you have any questions or observations about using Reflection to create plug-ins, let me know by leaving a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

9 comments October 9th, 2007

Rolling Your Own Generic Functions

Rolling Your Own Generic FunctionsYou probably know that Generics, introduced to VB.NET in the .NET Framework 2.0, provide type safe Lists, Dictionaries, Stacks, Queues and other objects. But, did you know that you can use the same technique to build your own type safe functions? In this article, we’ll look at some of the basics of doing this.

Why Generics?

First, let’s look at why generics are important.

Prior to generics we had to base any general purpose routines either around a particular type or use System.Object. This meant that we couldn’t make a routine as general purpose as we might want or we had to use performance impacting boxing to place a value type, such as an integer, into a reference type. Plus we had to use type conversions in many places or, worse, not use Option Strict so that we could do implicit conversions.

With generics, we can work with any type but without incurring performance penalties associated with boxing/unboxing variables or doing any casting. More importantly, we’re insuring type safety and thus avoiding troublesome runtime errors. Using them also makes it easier to build single functions that can work with several different data types.

MyFunction(Of T)(…

To begin with, let’s look at how we can define generic type parameters in our own functions. Here’s a simple example that accepts a paramarray of values of a specified type and places then into a generic List of the specified type:

Private Function BuildList(Of T)(ByVal ParamArray values() As T) As List(Of T)
    Dim NewList As New List(Of T)
    NewList.AddRange(values)
    Return NewList
End Function

Notice that when the function is defined we specify a generic type first, (Of T), and then our parameters, followed by our return value. Here are some examples of calling this function:

'
'
Dim StringList As List(Of String) = BuildList(Of String)("test1", "Hello!", "Bye!")
'
'
Dim IntList As List(Of Integer) = BuildList(Of Integer)(1, 87, 48, 28, 24)
'
'

As you can see we’re calling the same function but using different data types.

You can also specify multiple types and you’re not limited to just using ‘T’ as the name, as we see in this example that merges two lists of the same size into a dictionary object:

Private Function MergeLists(Of TKey, TValue)(ByVal Keys As List(Of TKey), ByVal Values As List(Of TValue)) As Dictionary(Of TKey, TValue)
    Dim MergedDictionary As New Dictionary(Of TKey, TValue)
    If Keys.Count = Values.Count Then
        Dim Counter As Integer
        For Each Item As TValue In Values
            MergedDictionary.Add(Keys.Item(Counter), Item)
            Counter += 1
        Next
    End If
    Return MergedDictionary
End Function

Calling this function would look like these examples:

'
Dim MyItems As Dictionary(Of Integer, String) = MergeLists(Of Integer, String)(IntList, StringList)
'
'
Dim MyInventoryResults As Dictionary(Of Integer, InventoryItem) _
    = MergeLists(Of Integer, InventoryItem)(KeyList, MyInventoryItems)
'
'

Also, we can have specific types in our paramaters while returning a generic type. For example, this function accepts a DataTable and Integer and returns a List object of the specified type with data from the specified column index.

Public Function ColumnToList(Of T)(ByVal MyTable As DataTable, ByVal columnIndex As Integer) As List(Of T)
    Dim ReturnList As New List(Of T)
    For Each RowValue As DataRow In MyTable.Rows
        ReturnList.Add(DirectCast(RowValue(columnIndex), T))
    Next
    Return ReturnList
End Function

Any time when you’re coding and you think, “Well, I’ll have to have a separate routine for this data type, and this one, and this one, and this one too”, take the time to consider if using generics will work for you in that case. Often you’ll find that it will.

As always, if you have any questions or ideas on this topic, feel free to leave me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

8 comments October 5th, 2007

Introduction To FileSystemWatcher

Introduction To FileSystemWatcherA common behind-the-scenes operation is to watch for the arrival of new files in a folder. I’ve had several projects where I had to watch for files arriving via FTP or HTTP uploads and then move these files off the web server and process them elsewhere on the network. In this article, we’ll look at the basics of using the FileSystemWatcher class to monitor file activity.

Creating a FileSystemWatcher

FileSystemWatcher is a member of the System.IO namespace. Remember that you’ll either need to import this namespace or explicitly type it out to use this class. When you create a FileSystemWatcher object you can create it with no parameters, you can specify the path you want it to monitor or you can specify both the path and the filter you wish to use. Here are some examples:

Watcher = New FileSystemWatcher
'.
'.....
'.
Watcher = New FileSystemWatcher(WatchPath)
'.
'.....
'.
Watcher = New FileSystemWatcher(WatchPath, WatchFilter)

The path parameter/property can be any valid UNC file path so you can watch both local and networked drives. Make sure that your user has access right to any paths they will need to access. This is especially critical for Windows Service applications running under LOCAL SERVICE or NETWORK SERVICE built-in IDs. Remember these IDs will usually need to be give access to target folders by an administrator.

The filter parameter/property is used to determine which files will be watched. You can use standard wildcards to look for particular file types, for example “*.doc”, or for a specific file, for example “annual_report.xls”.

The NotifyFilter

There are two filter properties in the FileSystemWatcher, one, as we mentioned above, to determine the file name(s) to watch for and NotifyFilter which says what kind of file system events to watch. By default, the NotifyFilter property is set to watch for a file to be written or for the file or directory name to be changed. You can also check for the file size, file security, or attributes changing. This property is a bitwise mask so you’ll set it by using Or, like so:

 
'.
'.
Watcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
'.
'.

Asynchronous Watching

In some cases, you will want to have your application continue running while files arrive. I’ve found this to be the most common scenario. To do this, you’ll setup the information mentioned above, then you’ll want to add event handlers for each type of event you wish to capture. These are Changed, Created, Deleted, and Renamed. You can either declared the FileSystemWatcher as WithEvents or you can use AddHandler. WithEvents is handy for having Visual Studio provide the code snippets but is less flexible than using AddHandler. You will need to create the event handler routines for the events you want to handle.

Now that everything is ready, we can begin watching. To do this, we set the EnableRaisingEvents property to True. We can use this property to turn watching on and off.

Here’s our complete code:

Private Watcher As FileSystemWatcher

'
' Other class code here
'

Private Sub StartWatcher(ByVal WatchPath As String, ByVal WatchFilter As String)
    Watcher = New FileSystemWatcher(WatchPath, WatchFilter)
    Watcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
    AddHandler Watcher.Created, AddressOf OnCreated
    AddHandler Watcher.Changed, AddressOf OnModified
    AddHandler Watcher.Deleted, AddressOf OnModified
    AddHandler Watcher.Renamed, AddressOf OnRenamed
    Watcher.EnableRaisingEvents = True
End Sub

Private Sub OnCreated(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs)
    'Code for newly created files here
    If e.Name = "error.txt" Then
        'error file found, do something about it
    Else
        'processing as normal
    End If
End Sub

Private Sub OnModified(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs)
    'Code for changed or deleted files here
End Sub

Private Sub OnRenamed(ByVal sender As Object, ByVal e As System.IO.RenamedEventArgs)
    'Code for renamed file here
    If e.OldName.Contains("error") Then
        're-processing an error file
    Else
        'normal processing
    End If
End Sub

When a file meeting our criteria arrives or is changed in our target folder, the events will fire. We can use the ‘e’ parameter to determine the exact nature of the event and to get the file information as seen in the code for OnCreated and OnRenamed above. Note that the event arguments parameter is different for the Renamed event. It returns information about the new file and the old file.

Synchronous Watching

Sometimes you may want to wait for the arrival of a particular file before allowing your code to continue. You can use the FileSystemWatcher for this as well by using the WaitForChanged method. To use this method you will need to setup the FileSystemWatcher object as before with the path and filters. However, you will not need to add event handlers, but, if they are defined, they will be fired even if EnableRaisingEvents property is set to false.

There are two overloads for the WaitForChanged method. The first overload has a single parameter that indicates the type of event to be watched for, such as created or renamed. The second overload adds the timeout value in milleseconds. I would recommend not using the first since it will wait indefinitely for the event to occur.

Here is an example of using this method:

Dim Results As WaitForChangedResult = Watcher.WaitForChanged(WatcherChangeTypes.Created, 10000)
If Results.TimedOut Then
    'Operation timed out code
Else
    'regular processing code
End If

Working With Multiple Folders and File Types

Often you’ll have requirements to monitor several different folders. Depending upon your needs, there are a few different ways to handle this.

First, if you’re just monitoring a folder and its subdirectories, you can set the IncludeSubdirectories property to True. This will allow you to add in anything under your main target folder automatically.

What if you need to monitor multiple folders or multiple file types? Unfortunately, each FileSystemWatcher can only monitor one folder structure and one file type. In this case, we will want to create multiple instances of the object to handle each folder and file type combo. Remember though that each of these instances can use the same event handlers.

Tips and Tricks

You can use the InternalBufferSize property to increase the size of the memory buffer for this operation. This can help prevent missing file events in very active systems. However, it can impose memory and performance penalties so be careful about using it.

Keep the size of your event code small. This helps insure better performance and prevents lost events. You may want to consider using threading if the processing required for each file event is considerable.

If a folder is cut and pasted this is considered a rename operation, not a create operation. This has been known to be confusing to some people, particularly when they’re using this method to test their code.

File actions may raise multiple events so you will need to take precautions against processing the same file multiple times.

That’s all for this introduction to the FileSystemWatcher object. Let me know if you have any questions or further observations about this object by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

11 comments October 1st, 2007

Previous Posts


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives