Develop for Windows 7

Have you any plans on starting to develop applications for Windows 7 yet?

The Windows API Code Pack can be used to access some of the new features in Win7, but also some existing features in older version of the Windows OS. The team at Microsoft that are behind the code pack have just updated all the sample code so they now come in both VB as well as in C#, and they did a very good job with it too. So go have a look, it’s pretty neat.

Have fun.

At your service (part II) – ASMX Web Service vs WCF

Introduction

Last time I demonstrated how to develop a Windows Communication Foundation (WCF) service. This time we’re going to look at the differences between a ASP.Net WebService and a WCF service. The biggest difference between them is probably that a WebService only can be activated via HTTP and they are tightly coupled with ASP.Net HTTP pipeline. A WCF service on the other hand can be bound to a large variety of network protocols. It also doesn’t require that it is hosted on a web server, it can be hosted in a console application, in a Windows Forms app, or in a WPF application. However WCF does have an ASP.Net compatibility mode setting to enable WCF services to be configured like a web service and also mimic their behavior.

Data representation

A WebService relies on the XmlSerializer to serialize types into XML and back to a .Net type. The following is a list of the things XmlSerializer can serialize to and from XML.

  • Only the public properties (or fields) of an object.
  • Collections can be serialized only if the implement the IEnumerable or ICollection interfaces.
  • Classes that implements the IDictionary interface, such as Hashtable, cannot be serialized into XML.
  • You can use attributes from the System.Xml.Serialization namespace on your own classes and members to control how instances of that class will be serialized.
  • You can also generate classes that can be serialized into XML from definitions of the types in XML Schema using the xsd.exe command line tool.

Point 4 and 5 describes how you can define complex types (classes) that can be serialized to and from XML.

In WCF you would also usually begin with the definition of complex types which is done adding the DataContractAttribute and the DataMemberAttribute to the class and its members, as described in my earlier post. The DataContractAttribute can be used on classes or structures and the DataMemberAttribute on properties and/or fields, which can be either private or public.

A few important differences between the DataContractSerializer and the XmlSerializer are:

  • The XmlSerializer serialize all public fields and properties, while you have better control using the DataContractSerializer.
  • The DataContractSerializer has better performance over XmlSerializer.
  • The DataContractSerializer can serialize Hashtables.

Service Development

To develop a WebService you would normally decorate a class with the WebServiceAttribute and each method with the WebMethodAttribute. This is however not an optimal solution since it does not constitute a contract for the operations performed by the service. ASP.Net 2.0 tried to rectify that by allowing you to use those attributes on an interface as well. That is the preferred method of doing it since the service contract can be reused with various classes that can implement that interface.

A WCF service requires you to create a contract, since the ServiceContractAttribute only can be used on an interface. So a WebService allows you to constitute a contract but doesn’t enforce it while a WCF service do.

A WebService only incorpartes BasicHttpBinding while a WCF service can use a wide range of bindings, such as WSHttpBinding, NetTcpBinding, NetNamedPipeBinding, amongst others.

Hosting the service 

ASP.Net web services are hosted on a Web Server. A WCF service can be hosted on a Web Server but can just as well be hosted by a Console- or Windows Forms application.

Conclusion

I don’t want to make any conclusions about which technique is the best to use, because that depends on the specification. A WebService is usually easier to develop but are somewhat limited. A WCF service is more versatile but can be harder to develop. To make a true comparison you should really compare the two techniques if you want to host the service on a Web Server, such as IIS, since if you want to use another host you can’t use an ASP.Net WebService. I just leave the judgment up to you.

Have fun!

At your service (part I) – WCF tutorial in VB

Introduction

In this post I’m going to do a tutorial on Windows Communication Foundation, WCF. This tutorial is divided in 4 steps:

  1. Defining the WCF data and service contracts.
  2. Implementing the WCF service contract.
  3. Creating the service-host application.
  4. Create a client application that uses the service.

So without further ado, let’s get busy.

Here is where we are getting busy

We’re going to implement our WCF server as a simple console application so start Visual Studio and create a new Console project. But for now we just leave the Sub Main() empty, since we implement the server in step 3. We also need to add a couple of references, first of all we need to add a reference to the System.ServiceModel.dll, right click on the project node in the Solution Explorer and click Add>Reference and scroll down the list until you find it. We also need to add a reference to the System.Runtime.Serialization.dll, so repeat the earlier step to add that as well.

Before we start with the WCF specific details we’re going to create a Data Access Layer (a DAL) which our service will work against to retrieve data. For the purpose of this article I’ve made a very simple class that can return a list of persons, or a single person. This could be customer information or an employment roll or whatever. In this sample I’ve hardcoded a list of persons, in a real word application you would retrieve this data from a database.

Public Class DataAccess
  Private Shared _list As List(Of Person)
  Private Shared Function GetPersonList() As List(Of Person)
    If _list Is Nothing Then
      _list = New List(Of Person)
      With _list
        .Add(New Person(1, "Homer", "Simpson"))
        .Add(New Person(2, "Marge", "Simpson"))
        .Add(New Person(3, "Bart", "Simpson"))
        .Add(New Person(4, "Lisa", "Simpson"))
        .Add(New Person(5, "Maggie", "Simpson"))
      End With
    End If
    Return _list
  End Function

  Public Shared Function GetPerson(ByVal id As Integer) As Person
    Return (From p In GetPersonList() Where p.ID = id).FirstOrDefault
  End Function

  Public Shared Function GetPersons() As List(Of Person)
    Return GetPersonList()
  End Function
End Class

As you can see the methods returns either a List(Of Person) or a single Person object. We will create the Person class in the next step.

Defining the WCF data and service contracts

We need to create a data contract for each object a WCF service can return, we also need to mark each property that is returned as a DataMember. We do that by adding attributes to our class and its members. Add a new class to the project, make sure you import the System.ServiceModel and the System.Runtime.Serialization namespaces, that we added a reference to earlier, and add the following code to the class.

Imports System.ServiceModel
Imports System.Runtime.Serialization

<DataContract()> _
Public Class Person
  Private _id As Integer
  <DataMember()> _
  Public Property ID() As Integer
    Get
      Return _id
    End Get
    Set(ByVal value As Integer)
      _id = value
    End Set
  End Property

  Private _firstName As String
  <DataMember()> _
  Public Property FirstName() As String
    Get
      Return _firstName
    End Get
    Set(ByVal value As String)
      _firstName = value
    End Set
  End Property

  Private _lastName As String
  <DataMember()> _
  Public Property LastName() As String
    Get
      Return _lastName
    End Get
    Set(ByVal value As String)
      _lastName = value
    End Set
  End Property

  Public Sub New(ByVal id As Integer, ByVal firstName As String, ByVal lastName As String)
    _id = id
    _firstName = firstName
    _lastName = lastName
  End Sub
End Class

The next step is to create the service contract for our WCF service. This contract defines what kind of operations our service provides and are defined as interfaces.

<ServiceContract(Namespace:="http://demo.wcf.samples")> _
Public Interface IPerson
  <OperationContract()> _
  Function GetPerson(ByVal id As Integer) As Person
  <OperationContract()> _
  Function GetPersons() As List(Of Person)
End Interface

Notice that the interface is decorated with a ServiceContractAttribute, I also changed its namespace, specifying the namespace is a best practice to prevent the default namespace of “http://tempuri.org” being used. Each operation that our service provides must be marked with the OperationContractAttribute, which you can see that I used on the two methods.

OK, now we have our contracts set up so we now need to implement them which we do next.

Implementing the WCF service contract

Since the contract and the service interface have already been designed, creating the service is straightforward and only requires that the interface is implemented.

Public Class PersonService
  Implements IPerson

  Public Function GetPerson(ByVal id As Integer) As Person _
Implements IPerson.GetPerson Return DataAccess.GetPerson(id) End Function Public Function GetPersons() As List(Of Person) _
Implements IPerson.GetPersons Return DataAccess.GetPersons() End Function End Class

As you can see I simply call the methods in the DataAccess class, that we defined in the introduction, in the implementation of the two methods.

That’s it. Our service is all done. But to be able to use it from a client application later we need to create a service-host application, which will host our service objects. That will be our actual server application and we’ll start creating that next.

Creating the service-host application

As I mentioned in the introduction, we will implement our service-host as a simple console application. So open the module with the Sub Main() definition and import the System.ServiceModel and the System.ServiceModel.Description namespaces. The latter of the namespaces is needed to describe the behavior of the metadata. In our case we will allow a client to get the data via a HTTP GET request.

The first thing we need to do is to configure a base address for the service. We do that by creating a new URI that specifies the address, port number, and the path of our service. We can use any IP port number that is usually not occupied, in this example I will use port 8240.

Dim uri = New Uri("http://localhost:8240/demo/wcf/samples")

As the path of the service I picked the same as I did for the namespace of the service contract we created earlier (which was “http://demo.wcf.samples”).

Next we need to create a ServiceHost reference, to which we must pass the type that implements our service contract and the base address that we just specified.

Dim host As New ServiceHost(GetType(PersonService), uri)

Now that we have our ServiceHost object we need to add an endpoint that exposes the service. To do this, you must specify the type of the contract the endpoint is exposing, a binding, and the address of the endpoint. The contract is our interface, and in this demo we will be using the WSHTTPBinding as the binding, and for the address we simply use the string “PersonService”.

A WCF service can use almost any kind of binding, you can use http binding, tcp binding and so on.

We will also need to enable Metadata exchange, to do that we add a service metadata behavior, as I already mentioned we will allow a client to get data from the service via a HTTP GET request. When this is done all we have to do is to open our host and wait for client requests.

Try
  host.AddServiceEndpoint(GetType(IPerson), New WSHttpBinding, "PersonService")
  Dim behavior As New ServiceMetadataBehavior()
  behavior.HttpGetEnabled = True
  host.Description.Behaviors.Add(behavior)

  host.Open()
  Console.WriteLine("The service has been started.")
  Console.WriteLine("Press the ENTER key to terminate service.")
  Console.WriteLine()
  Console.ReadLine()
  host.Close()
Catch ex As CommunicationException
  Console.WriteLine("Error: {0}", ex.Message)
  host.Abort()
End Try

You can now run the application. Not much will happen though, a console window will be created and the message that the service is started is shown. What we need to do now is to create a client application that can use the service. We’ll do that in the next section.

Create a client application that uses the service

Start by launching a new instance of Visual Studio, and create a new Console Application project. Add a reference to the System.ServiceModel.dll.

The first thing we need to do is to get the meta data of the service, and create the proxy code. You can use the SvcUtil.exe command line tool to do so, but there is an easier way. We can let Visual Studio do this for us by adding a Service Reference. To do this we first must make sure our service is running. So switch back to the previous instance of Visual Studio and start the project. Now switch back to this instance of Visual Studio and right click on the project node in the Solution Explorer and select “Add Service Reference” in the context menu. In the dialog that pops up we type in the URI we specified for our service endpoint in the previous section (http://localhost:8240/demo/wcf/samples) and click on the Go button. You should get the result you can see in the image below.

image

Click on the OK button and wait a few seconds while Visual Studio creates the proxy code for you.

Our proxy client will get the name PersonClient() which we need to create an instance of to be able to call the methods our service exposes.

Public Sub Main()
  Dim client As New ServiceReference1.PersonClient()
  Dim pers As ServiceReference1.Person = client.GetPerson(1)
  If Not pers Is Nothing Then
    Console.WriteLine("Person with ID=1 is {0} {1}", _
                      pers.FirstName, pers.LastName)
  End If
  Console.WriteLine("Person list")
      
  For Each p In client.GetPersons()
    Console.WriteLine("{0}: {1} {2}", _
                      p.ID, p.FirstName, p.LastName)
  Next
  Console.ReadLine()
End Sub

Make sure the service is running before running this code.

Conclusion

That’s all the steps that is needed to create a simple WCF service. It does require more code than an ASP.Net Web Service, in which you basically slap a WebMethodAttribute() to a method and your done, but I like the fact that WCF services encourage developers to use the contract-first principles. Next time, in part 2 of this “At your Service” series, I will do a comparison of an ASP.Net Web Service contra a WCF Service. Until then:

Have fun!

Debugging a Windows Service

Introduction

In my last article I showed a simple example of how to create a Windows Service using VB. This time we’re going to have a look at how to debug the service from Visual Studio.

Since a service must run from the context of the Service Control Manager you can’t normally debug it in the same manner as you would any other project type. Normally you would need to build the project, install it using the InstallUtil.exe command line tool, and attach a debugger to the process while it’s running. Another approach is to create a separate project (console application) and call your main code from there.

Neither of these are an ideal way of doing the debugging so I’m going to show an alternative method, which you also can use to run your service from the command line, just like any other application.

Converting the service into a command line tool

When you create a Windows Service project in Visual Studio 2008, you get a ServiceBase designer to which you add controls and your code to. Normally you would, at the very least, override the OnLoad() and the OnStop() methods. But the designer also creates a shared (static) Main() method for you, which is the real starting point of the service. To be able to see that you need to open the designer generated code file. In VB this file is normally hidden, so you need to press the Show all files button in the Solution Explorer.

image

The Main() method looks like this (with some comments removed).

<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Public Shared Sub Main()
  Dim ServicesToRun() As System.ServiceProcess.ServiceBase
  ServicesToRun = _
New System.ServiceProcess.ServiceBase() {New FileWatcherService} System.ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub

A Main() method can receive arguments from the command line, you just have to add a string array as a parameter of the method. The whole idea is that if a specific command line switch is passed to the executable it should not act as a Windows Service but instead run as any other EXE file. So I rewrote the above method to this:

' The main entry point for the process
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Public Shared Sub Main(ByVal args() As String)
  Dim runAsService As Boolean = True
  For Each arg As String In args
    Select Case arg.ToLower
      Case "/c", "-c"
        runAsService = False
    End Select
  Next
  If runAsService Then
    Dim ServicesToRun() As System.ServiceProcess.ServiceBase
    ServicesToRun = _
New System.ServiceProcess.ServiceBase() {New FileWatcherService} System.ServiceProcess.ServiceBase.Run(ServicesToRun) Else Dim service As New FileWatcherService service.CommandLineExecution = True service.OnStart(New String() {""}) End If End Sub

If the /c or –c switch is found among the command line parameters then it will start as a regular program. As you can see, if the switch is found, instead of creating an instance of the ServiceBase class I create an instance of my service class directly and call its OnStart() method. I also added a CommandLineExecution property to the class so I can keep track of how it is supposed to be executed. If you need to set a breakpoint or step through the Main() method you need to remove the DebuggerNonUserCode attribute, otherwise Visual Studio will just run through this method without stopping (this is what you normally would want to do with designer created code).

Now I also needed to make some changes to the OnStart() method.

Protected Overrides Sub OnStart(ByVal args() As String)
  Dim handle As IntPtr = Me.ServiceHandle
  If Not Me.CommandLineExecution Then
    _serviceStatus.currentState = Fix(State.SERVICE_START_PENDING)
    SetServiceStatus(handle, _serviceStatus)
  End If
  Dim logMessage As String = String.Empty
  If Not ReadSettings(logMessage) Then
    WriteLogMessage(logMessage, EventLogEntryType.Error)
    _serviceStatus.currentState = Fix(State.SERVICE_STOPPED)
    If Not Me.CommandLineExecution Then
      SetServiceStatus(handle, _serviceStatus)
    End If
  Else
    If Not String.IsNullOrEmpty(logMessage) Then
      WriteLogMessage(logMessage, EventLogEntryType.Information)
    End If
    'Start the file watching...
    With FileSystemWatcher1
      .BeginInit()
      .Filter = _fileMask
      .IncludeSubdirectories = _includeSubFolders
      .Path = _folderName
      .EnableRaisingEvents = True
      .EndInit()
      If Not Me.CommandLineExecution Then
        _serviceStatus.currentState = Fix(State.SERVICE_RUNNING)
        SetServiceStatus(handle, _serviceStatus)
      Else
        Threading.Thread.Sleep(Threading.Timeout.Infinite)
      End If
    End With
  End If
End Sub

If the CommandLineExecution property is set to True I skip all the calls to the SetServiceStatus() Win32 API function. I also end the method by letting the current thread sleep for infinity, if I didn’t do that the program would just exit when it reached the end of the method.

I also made a slight change to the WriteLogMessage() method, if the application isn’t running as a service there is no reason to do the logging to the Event Viewer. Instead it simply shows a message box.

Private Sub WriteLogMessage(ByVal message As String, _
ByVal type As EventLogEntryType) If Not Me.CommandLineExecution Then If Not EventLog.SourceExists("File Observer") Then EventLog.CreateEventSource("File Observer", "File Observer Log") End If Dim log As New EventLog() log.Source = "File Observer" log.WriteEntry(message, type) Else MsgBox(String.Format("{0}: {1}", type.ToString, message)) End If End Sub

Debug the service

To be able to run this service as a regular application from Visual Studio you must pass the command line switch /c. You can specify command line arguments on the Debug tab of the project properties dialog.

image

Conclusion

In this post I showed you how to turn a Windows Service into a regular executable using a command line switch to allow you to debug it from Visual Studio. Of course, instead of a command line switch you could instead just check if the application is in debug or release mode. But I wanted to be able to run the service as a regular application even after it was compiled and deployed in release mode.

Have fun!

Creating a Windows Service using VB.Net

Introduction

Yesterday I got a call from my brother, or actually he sent me a message over MSN. He wanted to know if I could help him create a program with a very specific requirement. Where he works they have a system that creates a lock file when you enter a new journal into the system. However because of a bug (?) in that system, this file is not always deleted after the journal have been entered. If this file is not removed, no more journals can be entered and the system runs amok.

So my brother wanted a program that could monitor a folder for this file, if it’s not removed within a specified time, say 1 minute, an e-mail notification is supposed to be sent. Since this program was supposed to run on the server, it needed to be a Windows Service.

Creating a Windows Service

Creating a Windows Service might not be something you do on a daily bases, during my career I’ve only made 3 or 4 of them, and this one was the very first I’ve created using .Net. Developing a Windows Service used to be pretty darn difficult, but not any more. As it turned out it’s fairly easy these days.

You start by selecting the Windows Service project type in the New Project dialog box in Visual Studio.

image

Doing that will give you a ServiceBase designer on which you can drop your controls, but since a Service normally don’t interact with the desktop, since it’s supposed to be running even if nobody is logged in, you shouldn’t use input controls such as text boxes or buttons. Using a Timer is a normal way of handling the work the service should do, but in my case I only needed a FileSystemWatcher, so I just dropped that on to the designer surface. The designer also have a handful of properties, many of which are named Can… such as CanPauseAndContinue and CanStop. If you set the CanPauseAndContinue property to True you can override the OnPaus and OnContinue methods. In my case I wasn’t interested in that but I did want an administrator to be able to stop the service so I left the CanStop property as True. If you, like me, leave the properties with their default settings you will have to override the OnStart and OnStop methods and I will cover that shortly.

I needed a way to store settings for this service, such as the time it would wait before sending an e-mail, the folder and file it was going to watch, and various SMTP and mail settings, such as the subject and the body text. To keep it as simple as possible I decided to add an App.Config file. To do that just right click on the project in the solution explorer and select Add > New Item, in the context menu. Find the Application Configuration template and click the Add button. Note, leave the name as app.config Visual Studio will automatically rename this file and copy it to the Bin folder when you build the project. To be able to read the config file you need to add a reference to System.Configuration.

I will not go into the details of using an app.config file but in short you need to add an <appSettings> section under the <configuration> node under which you add your own settings.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="emailSubject" value="Can somebody remove this file please?" />
    <!-- 
      more settings go here…
    --> 

You can then read these values using the ConfigurationManager.AppSettings() method (this requires that you have imported the System.Configuration namespace which we set a reference to earlier).

In my service I added a private method which I simply called ReadSettings. I will not show you all of that code since it’s mainly boiler plate, but a part of it looks like this:

Private Function ReadSettings(ByRef logMessage As String) As Boolean
  Dim emailRecipients As String()
  _eMailTo = New List(Of String)
  Try
    emailRecipients = ConfigurationManager.AppSettings("emailTo").Split(";"c)
  Catch ex As Exception
    logMessage = _
"No e-mail recipients with valid e-mails found, " & _
"
edit ""emailTo"" in the config file."
Return False End Try For Each email In emailRecipients email = email.Trim If Not String.IsNullOrEmpty(email) AndAlso IsValidEmail(email) Then _eMailTo.Add(email) End If Next If _eMailTo.Count = 0 Then logMessage = "No e-mail recipients with valid e-mails found." Return False End If Try _subject = ConfigurationManager.AppSettings("emailSubject") Catch ex As Exception logMessage = "No e-mail subject found" _subject = String.Empty End Try 'read the rest of the settings Return True End Function

This method takes a parameter, logMessage, by reference. In some cases, for example with the e-mail subject, it is allowed to leave that out of the config file and the application will simply send the e-mail without a subject. Other settings, like the address or addresses to send the e-mail to is required. The ReadSettings method will return False if some required setting was not found, or in the wrong format. The actual writing to the log is done by the OnStart method, or rather it’s done by another small helper method that is called by the OnStart method.

Private Sub WriteLogMessage(ByVal message As String, _
ByVal type As EventLogEntryType) If Not EventLog.SourceExists("File Observer") Then EventLog.CreateEventSource("File Observer", "File Observer Log") End If Dim log As New EventLog() log.Source = "File Observer" log.WriteEntry(message, type) End Sub

I put all validation rules in the ReadSettings() method so that when it’s time to send the e-mail, I know that I have e-mail addresses that are valid (or rather, that they have a valid form, not that I can check if the address itself really exists), and that the SMTP IP port is set to a valid integer and so on.

The OnStart() and OnEnd() methods

Even though you can override the constructor of the ServiceBase control, you shouldn’t really put initialization code there. This is because if the service is stopped and then restarted the constructor is not called again, but the OnStart() method is. So initialization should go into that method.

In my very specific case, I used a FileSystemWatcher to monitor the specified folder for the creation of the specified file. If the ReadSettings() method returned True I started monitoring the folder. If not I needed a way to stop the service from starting and write an error message to the event viewer. Unfortunately the OnStart() method does not have a way of signaling an error, so what you need to do is to call the SetServiceStatus() function which is a Win32 API function. Import the System.Runtime.InteropServices namespace and add the following code to your class.

<StructLayout(LayoutKind.Sequential)> _
Public Structure SERVICE_STATUS
  Public serviceType As Integer
  Public currentState As Integer
  Public controlsAccepted As Integer
  Public win32ExitCode As Integer
  Public serviceSpecificExitCode As Integer
  Public checkPoint As Integer
  Public waitHint As Integer
End Structure

Public Enum State
  SERVICE_STOPPED = &H1
  SERVICE_START_PENDING = &H2
  SERVICE_STOP_PENDING = &H3
  SERVICE_RUNNING = &H4
  SERVICE_CONTINUE_PENDING = &H5
  SERVICE_PAUSE_PENDING = &H6
  SERVICE_PAUSED = &H7
End Enum 

Private Declare Auto Function SetServiceStatus Lib "ADVAPI32.DLL" ( _
    ByVal hServiceStatus As IntPtr, _
    ByRef lpServiceStatus As SERVICE_STATUS _
) As Boolean
Private
_serviceStatus As SERVICE_STATUS

So the following is the code I used in the OnStart() method.

Protected Overrides Sub OnStart(ByVal args() As String)
  Dim handle As IntPtr = Me.ServiceHandle
  _serviceStatus.currentState = Fix(State.SERVICE_START_PENDING)
  SetServiceStatus(handle, _serviceStatus)
  Dim logMessage As String = String.Empty
  If Not ReadSettings(logMessage) Then
    WriteLogMessage(logMessage, EventLogEntryType.Error)
    _serviceStatus.currentState = Fix(State.SERVICE_STOPPED)
    SetServiceStatus(handle, _serviceStatus)
  Else
    If Not String.IsNullOrEmpty(logMessage) Then
      WriteLogMessage(logMessage, EventLogEntryType.Information)
    End If
    'Start the file watching...
    With FileSystemWatcher1
      .BeginInit()
      .Filter = _fileMask
      .IncludeSubdirectories = _includeSubFolders
      .Path = _folderName
      .EnableRaisingEvents = True
      .EndInit()
      _serviceStatus.currentState = Fix(State.SERVICE_RUNNING)
      SetServiceStatus(handle, _serviceStatus)
    End With
  End If
End Sub

So if everything works out the way it should I start the FileSystemWatcher by setting its EnableRaisingEvents property to True. In the OnStop() method I simply set this property to False to disable it.

When the FileSystemWatcher finds that the file that is being watched is created it raises the Created() event, in which I start a new thread that will simply sleep for the specified number of seconds and then check if the file still exists. If it does it sends the e-mail.

Private Sub FileSystemWatcher1_Created( _
    ByVal sender As Object, _
    ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Created
  If e.ChangeType = IO.WatcherChangeTypes.Created Then
    Dim thread As New Threading.Thread(AddressOf WatchFile)
    thread.Start(e.FullPath)
  End If
End Sub

Private Sub WatchFile(ByVal fullPath As Object)
  Dim fileName As String = CStr(fullPath)
  Threading.Thread.Sleep(_delayTime * 1000)
  If IO.File.Exists(fileName) Then
    SendMail()
  End If
End Sub

Private Sub SendMail()
  Dim mail As New System.Net.Mail.MailMessage
  For Each email In _eMailTo
    mail.To.Add(New Net.Mail.MailAddress(email))
  Next
  mail.From = New Net.Mail.MailAddress(_emailFrom)
  mail.Subject = _subject
  mail.Body = _body
  Dim smtpClient As New Net.Mail.SmtpClient(_smtpHost)
  With smtpClient
    .Port = _smtpPort
    If _requireAuthentication Then
      .Credentials = New Net.NetworkCredential(_authenticateName, _
_authenticatePassword) End If Try .Send(mail) Catch ex As Exception WriteLogMessage("Unable to send mail: " & ex.Message, _
EventLogEntryType.Error) End Try End With End Sub

Adding an installer to the project

Since this is a Windows Service it has to be installed as such so that it’s listed in the Service control panel applet. So you need to add an installer to the project. Note that this installer is not the same thing as a setup program, it will just add the necessary code that allows this application to be installed as a service using the InstallUtil.exe command line tool that comes with the .Net framework. More about that tool in a second.

To add an installer select your ServiceBase designer and right click on its surface and select Add Installer in the context menu. This will add a new Installer designer to your project that contains two component, a ServiceInstaller and a ServiceProcessInstaller.

Select the ServiceInstaller and change its DisplayName property. This will be the name that is listed in the control panel applet. You can also change the StartType property to Automatic if you want your service to start directly after it has been installed. In my case I left that property as Manual.

Now select the ServiceProcessInstaller and set the Account property to LocalSystem.

That’s it. You can now build the project. To do the installation open up a Visual Studio Command Prompt and type:

InstallUtil c:\thePath\theNameOfYourAssembly.exe

And presto! Your service should now be listed among the others in the Services control panel applet. Try to start and stop it from there. If you want to uninstall the service, which you must do if you need to make some changes to the source code, then type the following at the command prompt.

InstallUtil /u c:\thePath\theNameOfYourAssembly.exe

Conclusion

Even though this was a Windows Service with some very specific requirements I hope that this article have answered some questions on how you can create your own services.

Have fun!

Event horizon – Understanding custom events

Introduction

In this article I’m going to try to explain what custom events are and why you should use them in your code. As you will see the term custom event in this context is not just an event you have created for your own class, but also a custom way of storing the delegates for this event.

Most of this article is intended for the VB developer, but with the exception of VB specific parts, especially found in the Background Info section, the information here also applies to C# (but with a slightly different syntax of course).

Background info

If you have used VB or any other .Net language for an extended time, you have probably created one or two user controls, or regular classes that raises events. Events in the .Net framework are implemented as properties that accepts a delegate. A delegate is similar to a function pointer in C or C++ although a delegate is strongly typed. I wont dwelve into the difference between a function pointer and a delegate in this article, since that would be an article of its own. Instead I will just simplify and say that a delegate is an address to a method that will be called by the handler (in this case its the object that exposes the event).

If you want to handle an event raised by an object you can use the AddHandler statement. But VB also has a simplified solution using the Handles keyword. If you drop a Button on a Form you could then handle its click event like this:

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles Button1.Click
  'code for the click event goes here
End Sub

The above code will be called when the Click event occur for the object named Button1. This is made possible by another VB specific keyword that’s been around since VB5, the WithEvents keyword.

When you drop the button on the Form the designer will create the code that declares and initializes the component for you. The declaration of the button the designer creates looks like this:

Friend WithEvents Button1 As System.Windows.Forms.Button

You can use this syntax yourself in your code to handle events raised by objects without the need to call the AddHandler statement. However for clarity I will show the AddHandler approach as well. If the designer wouldn’t use the WithEvents keyword, you wouldn’t be able to use the Handles keyword either to handle the event.

Friend Button1 As System.Windows.Forms.Button

In this case you would need to use the AddHandler in our code.

Private Sub Form1_Load(ByVal sender As Object, _
                       ByVal e As System.EventArgs) Handles Me.Load
  AddHandler Button1.Click, AddressOf Button1_Click
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) 'No Handles keyword
  'code for the click event goes here
End Sub

Creating your own events

It’s very easy to let your own classes/controls expose events. In most cases you would probably declare your events like this within your class:

Public Event MySpecialEvent(ByVal sender As Object, ByVal e As EventArgs)

A class that have the above will expose a MySpecialEvent event. But this is not enough. It’s when you raise the event the code in the event handlers is being executed. So whenever it is time to raise MySpecialEvent you would use code like this:

RaiseEvent MySpecialEvent(Me, New EventArgs)

If you’re coming from a VB6 background, this will seem very familiar to you.

You might call the above a custom event, since that’s what it is. My class has a custom event called MySpecialEvent which I have implemented using the technique I just demonstrated. But as I mentioned in the introduction section, custom event (in the lack of a better name) in this context is much more than this. For Custom events you need to keep track of all the event handlers that is used. More about that in the next section.

Custom events = keeping track of event handlers

There is a problem with how we created our own events in the previous section: It can become a huge waste of memory resources.

Let me again take a regular Button in a Windows Forms application as an example. The Button component exposes no less than 68 different events. If they all would be declared with the Public Event EventName syntax, it would require that 68 fields needs to be created. Lets say a Form contains 10 buttons, that is 680 fields, and in the most likely scenario 670 of these are never used since we’re probably only interested in the Click event. So what we end up with are objects that takes longer to instantiate and more usage of heap memory that can’t be reclaimed, unless you remove the control from the Form and dispose it (and how often do you do that with controls you’ve added to a Form?).

So if you create your own user control or regular class that exposes many events you need a custom event storage. There is a special collection class called EventHandlerList in the Framework, available in the System.ComponentModel namespace, which we can use to store the event handlers.

Let’s say I create a class that contains a few typical mouse events and take advantage of the EventHandlerList to store all event handlers, I would write code similar to the following.

Public Class CommonMouseEvents

  Private events As New System.ComponentModel.EventHandlerList
  Public Custom Event Click As EventHandler
    AddHandler(ByVal value As EventHandler)
      events.AddHandler("OnClick", value)
    End AddHandler

    RemoveHandler(ByVal value As EventHandler)
      events.RemoveHandler("OnClick", value)
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
      Dim value As EventHandler = CType(events("OnClick"), EventHandler)
      value.Invoke(sender, e)
    End RaiseEvent
  End Event

  Public Custom Event DoubleClick As EventHandler
    AddHandler(ByVal value As EventHandler)
      events.AddHandler("OnDblClick", value)
    End AddHandler

    RemoveHandler(ByVal value As EventHandler)
      events.RemoveHandler("OnDblClick", value)
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
      Dim value As EventHandler = CType(events("OnDblClick"), EventHandler)
      If value IsNot Nothing Then
        value.Invoke(sender, e)
      End If
    End RaiseEvent
  End Event
  'Move event declarations go here...
End Class

Here we first create an instance of the EventHandlerList class, and then I declare my events.

Notice the Custom keyword and that the event must be declared as an EventHandler or one of its child classes. Inside the event declaration you must write code for the AddHandler(), RemoveHandler(), and RaiseEvent() procedures (the stub for these are added automatically by the designer in Visual Studio).

Now, the above is just the declaration of the events and the custom code to store, remove, and invoke the event handlers. You must still raise the events in the normal fashion, using the RaiseEvent statement.

What exactly are the EventHandlerList?

In the previous section I called the EventHandlerList a collection, but that is not really true. It doesn’t implement the IEnumerable interface, it is instead implemented as a linked list. That means that even though we save a great deal of memory space, we might have a trade-off in access speed since we need to search the list from front to end for an event handler. In the case a event handler doesn’t exist we need to traverse the whole list.

So why wasn’t this list implemented as a hash table instead? The answer is pretty simple, the list will probably not be very large. Normally you will probably not use more than say 10 events (and in most cases probably less than that) on a given object, and with that small amount of data a linked list is actually much faster than a hash table.

Have fun!

kick it on DotNetKicks.compimp itShout it

Run you later – Understanding deferred execution in LINQ

Introduction

In this article I’m going to try to explain one of the most misunderstood features of LINQ – deferred execution – and the impact it might have on your code if you don’t fully understand what it means.

What does deferred execution mean?

According to the dictionary the word deferred means delayed or postponed. So deferred execution in LINQ means that the actual execution of a query is postponed to a later time. Let’s say that you’re using LINQ to SQL and want to use the following LINQ query:

Dim cheapProducts = From p In db.Products _
                    Where p.ListPrice < 100 _
                    Select p

It’s easy to assume that the above will execute a query against the underlying database, but it wont. It will just create an IQueryable that has a reference to something that knows how this query can be executed (when it comes to LINQ to SQL this reference will point to an expression tree, but you don’t have to know about that since that’s just an implementation that the LINQ to SQL provider uses), but it will not run the actual query. LINQ has postponed, or deferred, the execution to a later time.

-To a later time, you say. So when is that exactly?

In LINQ the execution of a query is performed when you request the data, for example in a loop.

For Each prod In cheapProducts
  Console.WriteLine("The list price for {0} is {1}", prod.ProductName, prod.ListPrice)
Next

But you might request the data earlier. Take the following query as an example.

Dim productList = (From p In db.Products _
                   Where p.ListPrice < 100 _
                   Select p).ToList()

In this case we request that the result of the query is turned into a List(Of Product). To be able to do that the query has to be executed. But that doesn’t really mean that we didn’t have a deferred execution, it just wasn’t delayed for very long since we immediately request that the data should be turned into a list. This would also be true if we instead of requesting a list would call the Count() extension method or anything else that wouldn’t return an IEnumerable(Of T) or an IQueryable(Of T).

What kind of implications might this have on my code?

For the purpose of this article I’m going to use a Person class that only have a FirstName and LastName property and a little helper method that fills a List(Of T) with a number of persons, which will be used as the data source of our queries. In other words I’m going to use LINQ to Objects, but the same rules apply even if you use any other LINQ provider such as LINQ to SQL or LINQ to XML.

Public Class Person
  Private _firstName As String
  Public Property FirstName() As String
    Get
      Return _firstName
    End Get
    Set(ByVal value As String)
      _firstName = value
    End Set
  End Property

  Private _lastName As String
  Public Property LastName() As String
    Get
      Return _lastName
    End Get
    Set(ByVal value As String)
      _lastName = value
    End Set
  End Property

  Public Sub New(ByVal firstName As String, ByVal lastName As String)
    _firstName = firstName
    _lastName = lastName
  End Sub

  Public Shared Function GetPersonList() As List(Of Person)
    Dim list As New List(Of Person)
    With list
      .Add(New Person("Bart", "Simpson"))
      .Add(New Person("Lisa", "Simpson"))
      .Add(New Person("Maggie", "Simpson"))
      .Add(New Person("Homer", "Simpson"))
      .Add(New Person("Marge", "Simpson"))
      .Add(New Person("Ned", "Flanders"))
      .Add(New Person("Maude", "Flanders"))
      .Add(New Person("Rod", "Flanders"))
      .Add(New Person("Todd", "Flanders"))
    End With
    Return list
  End Function
End Class

Now let’s say we have the following code.

Public Sub Main()
  Dim personList As List(Of Person) = Person.GetPersonList()

  'Get a list of the Simpsons family
  Dim lastName As String = "Simpson"
  Dim persons = From p In personList _
                Where p.LastName = lastName _
                Select p

  lastName = "Flanders"
  For Each pers In persons
    Console.WriteLine("{0} {1}", pers.FirstName, pers.LastName)
  Next
End Sub

Which are the names that will be written to the console? If you guessed the names of the Simpsons, you haven’t paid attention. The query asks for all persons with the last name “Simpson”, but still the name of the Flanders are written out. Remember that the query is not executed when we define it but rather when we ask for the data. Since we change the lastName variable before the query is executed we have in fact changed the query.

The fact that the execution is delayed until we ask for the data also means that we can reuse the same query. Let’s make some slight changes to the last example.

Public Sub Main()
  Dim personList As List(Of Person) = Person.GetPersonList()

  'Get a list of the Simpson's family
  Dim lastName As String = "Simpson"
  Dim persons = From p As Person In personList _
                Where p.LastName = lastName _
                Select p

  For Each pers In persons
    Console.WriteLine("{0} {1}", pers.FirstName, pers.LastName)
  Next
  Console.WriteLine("---------------")
  'Change the last name
  lastName = "Flanders"
  'Reuse the query
  For Each pers In persons
    Console.WriteLine("{0} {1}", pers.FirstName, pers.LastName)
  Next
  Console.ReadLine()
End Sub

In this example we first write out the names of the Simpson family. Then we change the lastName variable and loop through it again. Since the query has been changed it will be executed a second time and we’ll get the names of the Flanders family. We reused the same query to get two different results.

Conclusion

LINQ is wonderful thing. It allows you to do complex things with very few lines of code and that can surely bring a big smile to your face. However, that smile can easily be turned into a stupid looking grin if you don’t understand deferred execution. If you don’t understand exactly when the query will be executed you might present completely erroneous data to your end users.

Have fun!

The Untouchables (part III) – Adding iterators to our immutable stack

Introduction

In my last post I showed you a VB translation of Eric Lippert’s immutable stack class. There was however one thing that was lost in translation. In Eric’s original code he made the class enumerable (added support for a For Each loop). Because C# has support for iterators with its yield keyword, that was very easy to do… in C#. VB currently doesn’t have this feature so to add the same support we need to implement both the IEnumerable(Of T) and the IEnumerator(Of T), which in turn requires the implementation of the non-generic IEnumarable and IEnumerator and also the IDisposable interfaces.

The Interfaces

Fig1

As you can see from the above image, that is 7 members that we have to implement. That might sound like a lot, but fortunately it’s mainly boiler-plate code. Firstly, the Reset() method of the IEnumerator interface is rarely used and in our case we will simply throw an NotImplementedException in that method. Secondly, we will end up with two GetEnumerator() methods and two Current() properties. But in our case we will simply make the non-generic versions of these members private and call the generic versions from them. Thirdly, in our case we will not change the code that the designer adds to the Dispose() method of the IDisposable interface, except for one little detail. The designer will mark the Dispose() method as Overridable, but since our Stack() class is sealed (NotInheritable) we only need to remove that keyword.

That leaves us with only 3 members to which we need to add our logic, the IEnumarable(Of T).GetEnumerator() method, the IEnumerator(Of T).Current() property, and the IEnumerator.MoveNext() method.

The implementation

To add support for all of this we first have to make a change to our IStack(Of T) interface.

Public Interface IStack(Of T)
  Inherits IEnumerable(Of T), IEnumerator(Of T)

Function Push(ByVal value As T) As IStack(Of T) Function Pop() As IStack(Of T) Function Peek() As T ReadOnly Property IsEmpty() As Boolean End Interface

If you add this to your existing code, you will get the following in our class implementation:

image

To fix that simply put the text caret at the end of the Implements line and press the enter key. That will allow the designer to add the empty method and property procedures that we need to implement.

Since there will be two Current() properties and two GetEnumerator() methods, I simply rename the non-generic versions of these and make them private. From them we simply call the generic versions. In the Reset() method we simply throw an NotImplementedException.

Private Function IEnumerator_GetEnumerator() As System.Collections.IEnumerator _
    Implements System.Collections.IEnumerable.GetEnumerator
  Return GetEnumerator()
End Function

Private ReadOnly Property IEnumerator_Current() As Object _
    Implements System.Collections.IEnumerator.Current
  Get
    Return Current
  End Get
End Property
Public Sub Reset() Implements System.Collections.IEnumerator.Reset
  Throw New NotImplementedException()
End Sub

The important members to implement is the GetEnumertor() and the MoveNext() methods plus the Current() read-only property. In a regular class that implements these interfaces we would simply return Me in the GetEnumertor() method. However since our stack is immutable we can’t do that since we don’t change the current instance when we Pop a value from the stack. So instead we add a private instance of the object that we will change when needed. We also need a private field to hold the current value.

Private _enumerator As IStack(Of T) = Me
Private _currentValue As T

As you can see we initialize the _enumertor to be a reference to the current object,  Me. This is what we return from the GetEnumerator() method.

Public Function GetEnumerator() As  _
    System.Collections.Generic.IEnumerator(Of T) _
    Implements System.Collections.Generic.IEnumerable(Of T).GetEnumerator
  Return _enumerator
End Function

In the MoveNext() method we are supposed to return a boolean value if we can move to the next object. In our case we simply need to check our IsEmpty() property, if that is false then we can return another item. We also set the _currentValue field to the current value and Pop it from the stack.

Public Function MoveNext() As Boolean _
    Implements System.Collections.IEnumerator.MoveNext
  If Not _enumerator.IsEmpty Then
    _currentValue = _enumerator.Peek()
    _enumerator = _enumerator.Pop()
    Return True
  Else
    Return False
  End If
End Function

In the Current() property we simply return the _currentValue field that was set in the previous method.

Public ReadOnly Property Current() As T _
    Implements System.Collections.Generic.IEnumerator(Of T).Current
  Get
    Return _currentValue
  End Get
End Property

That’s pretty much it. We can now iterate throw our Stack using code similar to this:

Public Sub Main()
  Dim myStack As IStack(Of String) = Stack(Of String).Empty
  'init the stack
  For i As Integer = 0 To 25
    myStack = myStack.Push(ChrW(Asc("A") + i).ToString)
  Next
  'Use a For Each loop on the stack
  'Note, since a stack is last in-first out,
  'the alphabet will be written in reversed order here
  For Each s As String In myStack
    Console.Write(s)
  Next
End Sub

Conclusion

As you’ve seen, since VB currently doesn’t support iterators in the same manner as C# does, we need to add a lot more code to our class to support it. Most of it are boiler-plate code though so it’s not as hard as it might look at a first glance. If you’re interested in learning more about how to use iterators in VB I highly recommend that you read this Visual Studio Magazine article written by Bill McCarthy.

You can download the code for this article here.

Have fun!

The Untouchables (part II) – Creating an Immutable stack with VB

Introduction

In this article I will shamelessly “steal” the great work originally posted by Eric Lippert on his blog. However I will translate his code into VB and try to explain it from a VB developers point of view.

In my last post, I described what immutable objects are and what the advantage of using them would be. It also described how you could create an immutable class and use it as if it was value type. This time we are going to take this a step further and create an immutable stack.

An immutable stack, is that possible?

As Eric pointed out on his blog: This might sound a bit strange to you since a stack is by its very nature something that changes. You push stuff to it and pop things from it, last-in-first-out. So how can something like that be immutable? If we create a new stack object each time we push or pop something to/from the stack wouldn’t we then be allocating a great deal of memory? Well, in this case the answer is nope. Eric showed a very elegant way of saving memory, in some cases it might even be more efficient than a mutable version.

The idea is that you simply have a head object which is the last value or reference object (depending on what you’re storing on the stack) that was push onto the stack, and a tail which is a reference to the old stack. The state the stack was before the last item was pushed upon it.

Creating the Stack

As I’ve already mentioned, I did not create this code, all credit goes to Eric Lippert. All I have done is to translate it to VB, except for one detail. Eric implemented his stack as an IEnumerable(Of T), taking advantage of the iterator support that C# has with its yield keyword. Since VB currently doesn’t support that I simply didn’t implement it here. In the next part of this The Untouchables series I will however extend this stack class with support for iterators. As you will see it currently requires a whole lot more code in VB than it does in C#. If you’re interesting in learning more about how to use iterators in VB now, I would recommend that you read Bill McCarthy’s excellent article about the subject. But for now we just leave them out.

OK, onward! We are going to implement our stack using generics, so that you can use it to push any type onto the stack. The first thing we will do is to define an interface for our class.

Public Interface IStack(Of T)
  Function Push(ByVal value As T) As IStack(Of T)
  Function Pop() As IStack(Of T)
  Function Peek() As T
  ReadOnly Property IsEmpty() As Boolean
End Interface

If you have ever used a stack object before, you are probably accustomed that the Pop() method would return the value it just removed from the stack. In this case it doesn’t it simply returns another stack object without the value that was just popped. I must say that I agree with Eric here, that looking at the data should not require you to change it. A Pop which returns the value is a design flaw since it conflates two logically distinct and separate operations into one method. So in our case we use the Peek() method to look at the top value, and Pop() to remove it.

Our Stack class which will implement the above interface will have a constructor, but we will keep that private. You will get a new Stack object by calling the Push() and Pop() methods. However we also need a way to create an empty stack, otherwise we have nothing that we can Push or Pop anything to or from. Since every empty stack is the same, we will have a singleton empty stack that is created via a shared (static) method that we simply call Empty(). So we will be creating a new empty stack object (of strings in this example) in this manner:

Dim myStack As IStack(Of String) = Stack(Of String).Empty

Note that the myStack object above is not declared as Stack(Of String) but rather as our interface IStack(Of String). This is because our Empty() method returns an IStack(Of T) object that contains an instance to a private inner class called EmptyStack that like our Stack(Of T) class also implements the IStack(Of T) interface.

OK, here’s the full listing of the class.

Public NotInheritable Class Stack(Of T)
  Implements IStack(Of T)

  Private NotInheritable Class EmptyStack
    Implements IStack(Of T)

    Public ReadOnly Property IsEmpty() As Boolean _
Implements IStack(Of T).IsEmpty Get Return True End Get End Property Public Function Peek() As T Implements IStack(Of T).Peek Throw New Exception("Empty stack") End Function Public Function Pop() As IStack(Of T) Implements IStack(Of T).Pop Throw New Exception("Empty stack") End Function Public Function Push(ByVal value As T) As IStack(Of T) _
Implements IStack(Of T).Push Return New Stack(Of T)(value, Me) End Function End Class Private ReadOnly _head As T Private ReadOnly _tail As IStack(Of T) Private Shared ReadOnly _empty As New EmptyStack Public Shared Function Empty() As IStack(Of T) Return _empty End Function Public ReadOnly Property IsEmpty() As Boolean _
Implements
IStack(Of T).IsEmpty Get Return False End Get End Property Public Function Peek() As T Implements IStack(Of T).Peek Return _head End Function Public Function Pop() As IStack(Of T) Implements IStack(Of T).Pop Return _tail End Function Public Function Push(ByVal value As T) As IStack(Of T) _
Implements IStack(Of T).Push Return New Stack(Of T)(value, Me) End Function Private Sub New(ByVal head As T, ByVal tail As IStack(Of T)) _head = head _tail = tail End Sub End Class

Notice how each time we Push a new value onto the Stack we call our private constructor that create a new Stack object. However our _tail will simply contain a reference to the old stack, that way we conserve memory resources. Since more than one stack object can share the same tail it will actually be more effective than a regular mutable version of a Stack object.

Dim s1 As IStack(Of Integer) = Stack(Of Integer).Empty
Dim s2 As IStack(Of Integer) = s1.Push(10)
Dim s3 As IStack(Of Integer) = s2.Push(20)
Dim s4 As IStack(Of Integer) = s2.Push(30) 'shares its tail with s3

Remember that the Stack object is immutable so pushing a value onto the stack doesn’t change it. Instead it returns a new Stack object containing the newly pushed value. The following code will raise an exception “Empty Stack” since myStack is still empty.

Dim myStack As IStack(Of String) = Stack(Of String).Empty()
myStack.Push("Hello")
Console.WriteLine(myStack.Peek) 'raises an exception since myStack is empty

That is like calling the Replace() method of a string without assigning the return value to anything. It will not have changed the immutable string. The correct way of doing the above would be this:

Dim myStack As IStack(Of String) = Stack(Of String).Empty()
myStack = myStack.Push("Hello") 'change the reference of myStack
Console.WriteLine(myStack.Peek) 'writes "Hello"

OK, next time I’m going to extend our Stack class to add support for iterators, so that we can use a For Each loop on our stack object. So stay tuned…

Until then, have fun!

The Untouchables – Creating Immutable objects with VB

There are many articles available on the Internet about immutable objects in .Net. Unfortunately almost all of them are addressed toward C# developers. In this article I’m going to rectify that by providing some information on the subject aimed toward the VB developer.

Immutable objects are a very simple yet powerful concept within programming. An object is immutable if its state cannot change after it has been created, which means that all its members need to be read-only. The integer number 1, for example, is an immutable number. There is nothing you can do that changes it. You can’t make it into an even number, you can’t bribe it, and you can’t make it jump of joy. Yes, you can add 5 to it, and yes you can multiply it with 2, but that doesn’t change 1, instead you end up with another immutable number.

System.String

In .Net the most well-known immutable object is the String. Once you have created a string you can’t change it, you can only create other strings. It’s easy to forget that fact and sometimes you might write code like this:

Dim str As String = "Foo"
str.Replace("F", "f")

The above doesn’t change the str value, the Replace method returns a new string object containing the new text.

Dim str As String = "Foo"
str = str.Replace("F", "f")

Now, some might argue that we above have changed str, and we have, we have changed it’s reference to point to a new string, stored in another place on the heap. But we have not changed the original string “Foo”, we simply just don’t have any reference to the original string anymore, which means that the garbage collector will kick in sooner or later and clean up that memory for us.

Advantages of immutable objects

So what are the advantages of creating our own immutable objects? Well, first of all, since its state can’t be changed, the hash code of the object never changes either. That means we can safely use them as keys in hash tables. Another advantage is that we can compare two objects with equivalence. You can compare two different string objects in the same manner as you would with value types.

Public Function CheckPassword(ByVal password As String) As Boolean
  Dim mySecretPassword = "verySecret"
  If password = mySecretPassword Then
    Return True
  Else
    Return False
  End If
End Function

Public Sub Main()
  Console.Write("Enter password: ")
  Dim pass As String = Console.ReadLine
  If CheckPassword(pass) Then
    Console.WriteLine("Access allowed")
  Else
    Console.WriteLine("Access denied")
  End If
End Sub

Even though password and mySecretPassword are two different instances of string, we can still compare them in the same manner as you would do with value types (such as Integers or Doubles). This is possible because we can assume that the identity of an immutable object is its state. If the state could be changed we could not make that assumption.

But the killer argument to use immutable objects is because they simplify multithreading. Why is it that writing proper multithreaded applications are so hard? As Patrick Smacchia points out in this blog post, it’s because it’s hard to synchronize threads accesses to resources (objects or other OS things). The reason that this is so hard is because it’s hard to guarantee that there won’t be any race conditions between the multiple write and read accesses done by multiple threads on multiple objects.

If you had a hard time understanding the previous paragraph then think about it like this: You want to buy a new computer, but you’re not sure you have enough cash to get one. So you check your bank account over the Internet, and sure enough you have just enough to get the latest and best computer on the market. So you run down to the local computer store, but when you’re trying to pay using your Visa (or whatever card you use), your bank rejects the transaction. Why? Well, after the time you checked your balance but before you tried to pay for the computer, your wife (or significant other), which whom you share the bank account with, has bought a new coat (or something other less important thing compared to the computer you wanted). This is an example of a race condition that could happen between two separate threads. One thread checks a resource and then want to change it, or make some other assumption based on the current state, but between the check and the change another thread have already changed the state of the resource. But if the resource was immutable its state cannot be changed and are therefore more secure to use in a multithreaded environment.

So that gives us three great advantages of using immutable objects.

  1. They can be used as keys in a hash table.
  2. They simplify state comparison.
  3. They simplify multithreaded programming.

Creating your own immutable class

Just like the number 1 is immutable, the .Net framework provides two different keywords to create our own immutable values, Const and ReadOnly. Why do we have two keywords and what’s the difference between them? A field that is declared as a Const must be given a value when we create it, that means that there is no way for us to the let the user provide a value. The ReadOnly keyword on the other hand allows us to provide a value for the field in a constructor.

Public Class Person
  Private Const _age As Integer = 21
  Private ReadOnly _name As String

  Public Sub New(ByVal name As String, ByVal age As Integer)
    _name = name 'This is OK
    _age = age 'This will not compile
  End Sub
End Class

The true immutable value is the Const, but the ReadOnly keyword provides us with something that can be initialized when the object is created and then never change again which provides us with some flexibility.

In the rest of this article I will create an immutable Rectangle class. A rectangle has a top-left corner and a bottom-right corner. These four value (Top, Left, Right, and Bottom) are the only things we really need to describe a rectangle. Since the class is immutable we can only set these values, or properties, when we create a new rectangle object.

Private ReadOnly _left As Integer
Public ReadOnly Property Left() As Integer
  Get
    Return _left
  End Get
End Property

So the class have the above property, and three more for the Top, Right, and Bottom values, which are all declared in the same manner. As you see I didn’t only make the property read-only but the backing field as well. This is important! If the class should be treated as immutable, the class itself should not be able to change the value either. I also created a Width and a Height property, but you will never assign any values to these properties since they can be calculated.

Public ReadOnly Property Width() As Integer
  Get
    Return _right - _left
  End Get
End Property

Public ReadOnly Property Height() As Integer
  Get
    Return _bottom - _top
  End Get
End Property

The values are provided to the constructor.

Public Sub New(ByVal left As Integer, _
               ByVal top As Integer, _
               ByVal right As Integer, _
               ByVal bottom As Integer)
  If bottom < top OrElse right < left Then
    Throw New Exception( _
      "Left cannot be larger than Right and Top cannot be larger than Bottom.")
  Else
    _left = left
    _top = top
    _right = right
    _bottom = bottom
  End If
End Sub

The class also provides two different methods, Intersect and Union. Both of these creates a new rectangle object. The dashed red rectangle in the following image shows what a union between the yellow and the green rectangle would result in.

image

The next image shows the intersection of the yellow and the green rectangle.

image

If a union or an intersection of the two rectangles can’t be created the methods return Nothing (null). Since there are an IntersectRect and an UnionRect function provided by the Win32 API, I didn’t bother about writing the logic for these methods myself.

Private Declare Function IntersectRect Lib "user32" ( _
  ByRef lpDestRect As RECT, _
  ByRef lpSrc1Rect As RECT, _
  ByRef lpSrc2Rect As RECT) As Integer

Private Declare Function UnionRect Lib "user32" ( _
  ByRef lpDestRect As RECT, _
  ByRef lpSrc1Rect As RECT, _
  ByRef lpSrc2Rect As RECT) As Integer

<StructLayout(LayoutKind.Sequential)> _
Private Structure RECT
  Public Left As Integer
  Public Top As Integer
  Public Right As Integer
  Public Bottom As Integer
End Structure

I however needed to be able to convert my object into the RECT structure that these functions uses, so I wrote a quick little private helper method. I made this method shared (static) so I could use it on any rectangle object.

Private Shared Function ToRect(ByVal r As Rectangle) As RECT
  ToRect.Left = r.Left
  ToRect.Top = r.Top
  ToRect.Bottom = r.Bottom
  ToRect.Right = r.Right
End Function

With this in place, creating the methods was a breeze.

Public Function Intersect(ByVal other As Rectangle) As Rectangle
  If other Is Nothing Then
    Return Nothing
  Else
    Dim r1, r2, r3 As RECT
    r1 = Rectangle.ToRect(Me)
    r2 = Rectangle.ToRect(other)
    If IntersectRect(r3, r1, r2) <> 0 Then
      Return New Rectangle(r3.Left, r3.Top, r3.Right, r3.Bottom)
    Else
      Return Nothing
    End If
  End If
End Function

Public Function Union(ByVal other As Rectangle) As Rectangle
  If other Is Nothing Then
    Return Nothing
  Else
    Dim r1, r2, r3 As RECT
    r1 = Rectangle.ToRect(Me)
    r2 = Rectangle.ToRect(other)
    If UnionRect(r3, r1, r2) <> 0 Then
      Return New Rectangle(r3.Left, r3.Top, r3.Right, r3.Bottom)
    Else
      Return Nothing
    End If
  End If
End Function

OK, so that’s all the logic in this class. But since we want this class to act as a value type we need to override the Equals() method. However whenever you override that method you also need to override the GetHashCode() method. The hash code of one Rectangle must be equal to another identical Rectangle. That is two rectangles with the same top, left, bottom, and right values.

Public Overrides Function GetHashCode() As Integer
  Return (_top.GetHashCode Or _left.GetHashCode) Or _
         (_bottom.GetHashCode Or _right.GetHashCode)
End Function

Public Overrides Function Equals(ByVal obj As Object) As Boolean
  If obj IsNot Nothing AndAlso obj.GetType() Is Me.GetType() Then
    Dim other As Rectangle = CType(obj, Rectangle)
    Return (other.Left = Me.Left AndAlso other.Right = Me.Right) AndAlso _
           (other.Top = Me.Top AndAlso other.Bottom = Me.Bottom)
  Else
    Return False
  End If
End Function

We also want to be able to compare one Rectangle object to another using the = (equal) operator, please note that this is not the assignment operator which you can’t overload using VB since that is really a statement and not an operator. If we overload the equal operator we also need to overload its opposite, the not equal <> operator. Operator overloads are always shared (static).

Public Shared Operator =(ByVal r1 As Rectangle, _
                         ByVal r2 As Rectangle) As Boolean
  If r1 Is Nothing Then
    Return (r2 Is Nothing)
  Else
    Return r1.Equals(r2)
  End If
End Operator

Public Shared Operator <>(ByVal r1 As Rectangle, _
                          ByVal r2 As Rectangle) As Boolean
  Return Not (r1 = r2)
End Operator

So that’s it, put it all together and you’ve just created your own immutable class. OK, for your convenient I’ll show you the complete class below.

Imports System.Runtime.InteropServices
Public Class Rectangle
  Private Declare Function IntersectRect Lib "user32" ( _
    ByRef lpDestRect As RECT, _
    ByRef lpSrc1Rect As RECT, _
    ByRef lpSrc2Rect As RECT) As Integer

  Private Declare Function UnionRect Lib "user32" ( _
    ByRef lpDestRect As RECT, _
    ByRef lpSrc1Rect As RECT, _
    ByRef lpSrc2Rect As RECT) As Integer

  <StructLayout(LayoutKind.Sequential)> _
  Private Structure RECT
    Public Left As Integer
    Public Top As Integer
    Public Right As Integer
    Public Bottom As Integer
  End Structure

  Private ReadOnly _left As Integer
  Public ReadOnly Property Left() As Integer
    Get
      Return _left
    End Get
  End Property

  Private ReadOnly _top As Integer
  Public ReadOnly Property Top() As Integer
    Get
      Return _top
    End Get
  End Property

  Private ReadOnly _right As Integer
  Public ReadOnly Property Right() As Integer
    Get
      Return _right
    End Get
  End Property

  Private ReadOnly _bottom As Integer
  Public ReadOnly Property Bottom() As Integer
    Get
      Return _bottom
    End Get
  End Property

  Public ReadOnly Property Width() As Integer
    Get
      Return _right - _left
    End Get
  End Property

  Public ReadOnly Property Height() As Integer
    Get
      Return _bottom - _top
    End Get
  End Property

  Public Sub New(ByVal left As Integer, _
                 ByVal top As Integer, _
                 ByVal right As Integer, _
                 ByVal bottom As Integer)
    If bottom < top OrElse right < left Then
      Throw New Exception( _
        "Left cannot be larger than Right and Top cannot be larger than Bottom")
    Else
      _left = left
      _top = top
      _right = right
      _bottom = bottom
    End If
  End Sub

  Private Shared Function ToRect(ByVal r As Rectangle) As RECT
    ToRect.Left = r.Left
    ToRect.Top = r.Top
    ToRect.Bottom = r.Bottom
    ToRect.Right = r.Right
  End Function

  Public Function Intersect(ByVal other As Rectangle) As Rectangle
    If other Is Nothing Then
      Return Nothing
    Else
      Dim r1, r2, r3 As RECT
      r1 = Rectangle.ToRect(Me)
      r2 = Rectangle.ToRect(other)
      If IntersectRect(r3, r1, r2) <> 0 Then
        Return New Rectangle(r3.Left, r3.Top, r3.Right, r3.Bottom)
      Else
        Return Nothing
      End If
    End If
  End Function

  Public Function Union(ByVal other As Rectangle) As Rectangle
    If other Is Nothing Then
      Return Nothing
    Else
      Dim r1, r2, r3 As RECT
      r1 = Rectangle.ToRect(Me)
      r2 = Rectangle.ToRect(other)
      If UnionRect(r3, r1, r2) <> 0 Then
        Return New Rectangle(r3.Left, r3.Top, r3.Right, r3.Bottom)
      Else
        Return Nothing
      End If
    End If
  End Function

  Public Overrides Function GetHashCode() As Integer
    Return (_top.GetHashCode Or _left.GetHashCode) Or _
           (_bottom.GetHashCode Or _right.GetHashCode)
  End Function

  Public Overrides Function Equals(ByVal obj As Object) As Boolean
    If obj IsNot Nothing AndAlso obj.GetType() Is Me.GetType() Then
      Dim other As Rectangle = CType(obj, Rectangle)
      Return (other.Left = Me.Left AndAlso other.Right = Me.Right) AndAlso _
             (other.Top = Me.Top AndAlso other.Bottom = Me.Bottom)
    Else
      Return False
    End If
  End Function

  Public Shared Operator =(ByVal r1 As Rectangle, _
                           ByVal r2 As Rectangle) As Boolean
    If r1 Is Nothing Then
      Return (r2 Is Nothing)
    Else
      Return r1.Equals(r2)
    End If
  End Operator

  Public Shared Operator <>(ByVal r1 As Rectangle, _
                            ByVal r2 As Rectangle) As Boolean
    Return Not (r1 = r2)
  End Operator
End Class

Have fun.