VB class libraries and Global namespaces with Visual Studio 2012

0
404

From the routine collections of the 80s to today, the history of bookstores evolves with the same purpose of creating reusable code.

With .NET, collections have become class libraries, that is, assembly or, more colloquially, DLLs . These libraries group under one name many classes, usually homogeneous among them, that with their methods allow to define a reusable code. The advantages are remarkable:

  • for those who create libraries, just think of the libraries of third-party components created for sale without having to distribute the source code;
  • for those who use them, because they simplify the work, reduce development and test times and increase productivity: the code of the libraries is already tested and there is no need to “reinvent the hot water”.

Create class library with Visual Studio

Naturally also in Visual Studio 2012 we can create class libraries ..

Visual Studio 2012 provides all the tools necessary to create, deploy and use class libraries. These tools now include a new feature that is an absolute novelty for Visual Studio: the Global namespace.

In this article we will talk about this very important namespace, but first we make a small review on the standard and custom namespaces (defined by the developers). We will then see what changes with the introduction of the new Global namespace and why it is so important.

The namespaces

Namespaces are conceptually similar to containers and serve to organize the code in well-defined units. They are organized hierarchically: each namespace can contain one or more classes, but also other namespaces. Each second-level namespace can contain other namespaces and classes, and so on, in a hierarchical structure that is also very complex and with many levels.

It is very important to organize the namespace and class hierarchy well, because a disordered hierarchy causes confusion in the developer using the library, causing the loss of all the benefits that one wanted to obtain.

The .NET Framework is also organized in this way, with many nested namespaces such as Chinese boxes. Each namespace groups all the classes that are part of a specific category: for example, the namespace System.IOcontains all the classes needed to work with files, folders and disks, with input and output streams and so on.

Here we also find another specialized namespace: Compression, IsolatedStorage, Packaging, Pipes and Ports. In turn, these namespaces contain other classes associated with the specific category. For example, the namespace Compressioncontains the classes necessary to manage the compressed files.

The Default namespace

Even if we do not realize it, in our projects we always use at least one namespace: the Root namespace ( namespace “root”). In the documentation available on the network, in some cases, you may find this item also referred to as the Default namespace, but you can consider it as a synonym.

To verify that what we have said is true, you can open any Visual Studio solution and examine the properties of the project. In Applicazionefact, on the card we find a property named Root namespace:

The "Root Namespace" property of a project
The “Root Namespace” property of a project

As you can see in the figure, the name of the project namespace is the same as the name of the project and the assembly, but you can modify it according to your preferences (the name can not start with a numeric character).

Define the namespaces in the code

Anyone can define new namespaces in Visual Studio projects, even nesting them in multi-level namespaces. For example, we can define a code like the following:

<pre class=”brush: php; html-script: true”>
Namespace MyNamespace

Public Class Class1
here we write the code of the Class1 class
End Class

Namespace MyNamespace2

Public Class Class2
here we write the code of the Class2 class
End Class

End Namespace

Namespace MyNamespace3

Public Class Class3
here we write the code of the Classe3 class
End Class

Namespace MyNamespace4

Public Class Class4
here we write the code of the Classe4 class
End Class

End Namespace
End Namespace
End Namespace
</pre>

To access the various classes we must use a syntax that takes into account the whole “path” that you need to follow to reach the class, not very different from what you normally do in the file system to indicate a file contained in one of the subfolders . For example, if we want to access the Classe1we can use the reference:

<pre class=”brush: php; html-script: true”>
MyNamespace.Classe1
</pre>

To access the Classe4, however, we must use the reference:

<pre class=”brush: php; html-script: true”>
MyNamespace.MyNamespace3.MyNamespace4.Classe4
</pre>

Because namespaces always have a type of access level Public, we can freely access namespaces from anywhere in the code.

Let’s try now to see an example with a trial application.

“Traditional method” in a Visual Basic application

We consider as “traditional method” what has always been done before the introduction of the new Global namespace. Later we will see what changes using Global.

After creating an application of type WPF (which we have called MyLibrary_VS2012_01_VB), we insert three text boxes ( Valore1, Valore2e Risultato), three type controls Label for the descriptions and two buttons ( Somma1and Somma2), arranged as shown:

The first trial application
The first trial application

The XAML code is as follows:

<pre class=”brush: php; html-script: true”>
<Window xmlns = “http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns: x = “http://schemas.microsoft.com/winfx/2006/xaml”
xmlns: d = “http://schemas.microsoft.com/expression/blend/2008”
xmlns: mc = “http://schemas.openxmlformats.org/markup-compatibility/2006”
mc: ignorable = “d”
x: Class = “MainWindow” Title = “MainWindow” Height = “330” Width = “394”>

<Grid Margin = “10,0,2,3”>

<TextBox x: Name = “Value1” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Height = “37” TextWrapping = “Wrap” Text = “0”
Width = “180” Margin = “140.28,0,0” FontSize = “20” />

<TextBox x: Name = “Value2” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Height = “37” TextWrapping = “Wrap” Text = “0” Width = “180”
Margin = “140,70,0,0” FontSize = “20” />

<Button x: Name = “Sum1” Content = “Sum without Global” HorizontalAlignment = “Left”
VerticalAlignment = “top”
Width = “275” Margin = “45,124,0,0”
FontSize = “20” />

<Button x: Name = “Sum2” Content = “Sum with Global” HorizontalAlignment = “Left”
VerticalAlignment = “top”
Width = “275” Margin = “45,160,0,0”
FontSize = “20” />

<Label Content = “Value 1” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Margin = “45,24,0,0” FontSize = “20” />

<Label Content = “Value 2” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Margin = “45,66,0,0” FontSize = “20” />

<Label Content = “Result” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Margin = “45,221,0,0” FontSize = “20” />

<TextBox x: Name = “Result” HorizontalAlignment = “Left” VerticalAlignment = “Top”
Height = “37” TextWrapping = “Wrap” Text = “0” Width = “180”
Margin = “140,225,0,0” FontSize = “20” />
</ Grid>
</ Window>
</pre>

The goal we set ourselves is to add the two values entered in the text boxes and insert the result in the third text box. Obviously it is a simple objective to reach and also not very interesting: because of the simplicity of the task we can better focus on the real objective of the project, ie a better definition of a class library.

Add a name class Class1.vbin the Visual Basic project, open the file with a double-click and enter the following code:

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_01_VB
Public Class Class1
Public Function Somma(ByVal valore1 As Long, ByVal valore2 As Long) As Long
Return valore1 + valore2
End Function
End Class
</pre>

This class exposes a function ( Somma) that takes two integers of type Longas input arguments and returns the sum. As we have already specified, the simplicity of the function is intended not to add an additional level of complexity. Of course, you can define any function, even something very complex.

After adding a new class named Class2.vb, enter the following code:

<pre class=”brush: php; html-script: true”>
Example: MyLibrary_VS2012_01_VB
Namespace Utilities

Public Class Class2
Public Function Sum (ByVal value1 As Long, ByVal value2 As Long) As Long
Return value1 + value2
End Function
End Class
End Namespace
</pre>

As you can see, it Class2contains exactly the same instructions as Class1, but in this case it is included in the namespace declaration Utilities. This name is invented, to follow the example you can choose the same name or the one you prefer.

At first glance, the namespace Utilities should be a top-level namespace, but as we will see, things are not exactly in these terms.

Now we have to activate the two buttons, so that by pressing them something useful happens.

Let’s go back to the file MainWindow.xamland double-click on both buttons, in order to create the empty schema of their event handlers Click. Then enter the following code:

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_01_VB
Class MainWindow
Private Sub Somma1_Click(sender As Object, e As RoutedEventArgs) _
Handles Somma1.Click

Result.Text = “0”
If IsNumeric(Valore1.Text) And IsNumeric(Valore2.Text) Then

Dim Utilities As New MyLibrary_VS2012_01_VB.Class1
Risultato.Text = Utilities.Somma(Long.Parse(Valore1.Text), Long.Parse(Valore2.Text)).ToString

Else

MessageBox.Show(“One of the two values is not numeric”)
End If
End Sub

Private Sub Somma2_Click(sender As Object, e As RoutedEventArgs) _
Handles Somma2.Click

Risultato.Text = “0”
If IsNumeric(Valore1.Text) And IsNumeric(Valore2.Text) Then
Dim Utilities As New MyLibrary_VS2012_01_VB.Utilities.Class2
Risultato.Text = Utilities.Somma(Long.Parse(Valore1.Text), Long.Parse(Valore2.Text)).ToString
Else
MessageBox.Show(“One of the two values is not numeric”)
End If
End Sub
End Class
</pre>

We have verified that both the text boxes have a valid numerical value: if both values are valid the sum is executed, if even one value is not numeric (text or blank) an error message is displayed.

The two methods are almost the same, except for the third instruction that looks like this:

<pre class=”brush: php; html-script: true”>
Dim Utilities As New MyLibrary_VS2012_01_VB.Class1
</pre>

and so:

<pre class=”brush: php; html-script: true”>
Dim Utilities As New MyLibrary_VS2012_01_VB.Utilities.Class2
</pre>

We will see later the motive of this difference. for now, let’s just start the application. After entering two numerical values in the first two text boxes, try pressing the first button. If the code is written correctly, we should see in the third text box the value resulting from the sum of the two values entered.

The same will happen by pressing the second button, proving that the two methods are absolutely equivalent.

Note, however, that in the code we had to insert an explicit reference to the root namespace ( MyLibrary_VS2012_01_VB). In the second case, then, we see that the namespace Utilities depends on the root namespace, that is, it is a second-level namespace, while we wanted it to become a main namespace, that is, a top-level namespace.

In the following figure we observe the position of the classes Class1and Class2in the class hierarchy of the application:

Class hierarchy in the Class View window
Class hierarchy in the Class View window

Let’s now continue with the Global namespace.

The Global namespace

Let us now try to improve the structure of the application using the reserved word Global .

First we modify the class declaration Class1and Class2in the following way (the code inside the two classes remains unchanged):

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_02_VB
Namespace Global
Public Class Class1
Public Function Somma(ByVal valore1 As Long, ByVal valore2 As Long) As Long
Return valore1 + valore2
End Function
End Class
End Namespace
</pre>

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_02_VB
Namespace Global.Utilities
Public Class Class2
Public Function Somma(ByVal valore1 As Long, ByVal valore2 As Long) As Long
Return valore1 + valore2
End Function
End Class
End Namespace
</pre>

Then we modify the calls present in the code of the event handlers. Click of the two buttons:

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_02_VB
Class MainWindow
Private Sub Somma1_Click(sender As Object, e As RoutedEventArgs) _
Handles Somma1.Click

Risultato.Text = “0”
If IsNumeric(Valore1.Text) And IsNumeric(Valore2.Text) Then
Dim Utilities As New Class1
Risultato.Text = Utilities.Somma(Long.Parse(Valore1.Text), Long.Parse(Valore2.Text)).ToString
Else
MessageBox.Show(“Uno dei due valori non è numerico”)
End If
End Sub

Private Sub Somma2_Click(sender As Object, e As RoutedEventArgs) _
Handles Somma2.Click

Risultato.Text = “0”
If IsNumeric(Valore1.Text) And IsNumeric(Valore2.Text) Then
Dim Utilities As New Utilities.Class2
Result.Text = Utilities.Somma(Long.Parse(Valore1.Text), Long.Parse(Valore2.Text)).ToString
Else
MessageBox.Show(“One of the two values is not numeric”)
End If
End Sub
End Class
</pre>

The change we have made to the code is very minimal, but the effects are very interesting. Let’s take a look at Visualizzatore classi, comparing the previous project with what we have just modified:

The structure of the modified Visual Basic project
The structure of the modified Visual Basic project

the structure is substantially identical.

What is Global?

Global is a new reserved word that defines a top-level namespace. Being only a top-level namespace, it can not be used to define a nested namespace, as in the following example:

<pre class=”brush: php; html-script: true”>
‘ ### incorrect definition! ###
Namespace MiaLibreria

Namespace Global.NuovaLibreria

‘ … code

End Namespace
End Namespace
</pre>

Avoiding collisions

Since Global defines a top-level namespace, it is possible to define lower-level namespaces within it, even with the same name as other namespaces already existing in the .NET Framework, without this being the cause of “collisions”.

Suppose, for example, to write a block of code like the following:

<pre class=”brush: php; html-script: true”>
‘ ### incorrect definition! ###
Namespace System.Text
Class CodificaTesto
‘ … code
End Class
End Namespace

Module Module1
Sub Main()
Dim encodes As New System.Text.CodificaTesto

‘ the following instruction will cause an error
‘ being compiled, because the namespace
‘ standard has lost the scope of visibility:

Dim sb As New System.Text.StringBuilder

End Sub
End Module
</pre>

While IntelliSense shows to recognize the class System.Text.CodificaTesto, we can see that it no longer recognizes the class System.Text.StringBuilder, a class of the .NET Framework.

This behavior may seem strange, but in reality it is normal: the namespace System.Textwe created, in fact, blocks the visibility of the namespace in the .NET Framework and exposes only the locally created namespace.

Extend a .NET Framework namespace with Global
The solution, in this case, comes from the word Global: using it, in fact, we can extend the namespaces of the .NET Framework with the greatest ease.

Let’s try to see the same case with the appropriate changes.

<pre class=”brush: php; html-script: true”>
‘ this definition works!
Namespace Global.Math
Public Class Operazioni
Public Function SommaIntera(ByVal valore1 As Long, ByVal valore2 As Long) As Long
Return valore1 + valore2
End Function
End Class
End Namespace

Module Module1

Sub Main()
Dim sum As New Math.Operazioni()
somma.SommaIntera(1, 2)
End Sub

End Module
</pre>

After the simple addition of Global to the namespace definition, both the standard classes of the .NET Framework (for example System.Text.StringBuilder, System.Math) and the extensions we have defined in our code (in this case System.Math.Operazioni) will be recognized.

We conclude with the last example that allows our class Operazionito become an extension of the namespace System.Math. To achieve this, let’s add some more changes.

We create a new Visual Studio solution and proceed with the same methods used in the previous examples.

In this case, however, instead of a class we will add a module ( Module1.vb). In this form we will insert the following code:

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_03_VB
Namespace Global.System.Math

Public Class Operazioni
Public Function SommaIntera(ByVal valore1 As Long, ByVal valore2 As Long) As Long
Return valore1 + valore2
End Function
End Class

End Namespace
</pre>

Within the module, we have defined the namespace Global.System.Mathand, in this case, the class Operazioni. The latter contains a single method of name SommaInterathat requires two arguments of type Long and, in turn, returns a value of type Long which represents the sum of the two input values.

In the file we MainWindow.xaml.vbmodify the code as follows:

<pre class=”brush: php; html-script: true”>
‘ Example: MyLibrary_VS2012_03_VB
Class MainWindow
Private Sub Somma1_Click(sender As Object, e As RoutedEventArgs) _
Handles Somma1.Click

If IsNumeric(Valore1.Text) And IsNumeric(Valore2.Text) Then

Dim Utilities As New System.Math.Operazioni()
Risultato.Text = Utilities.SommaIntera(Long.Parse(Valore1.Text), Long.Parse(Valore2.Text)).ToString()
Else
MessageBox.Show(“One of the two values ​​is not numeric”)
End If
End Sub
End Class
</pre>

In this case we have created an instance of the class System.Math.Operazionithat is exactly the class we have defined ourselves. If it were not for the class name, expressed in Italian, it would seem to be a class natively included in the namespace System.Math.

LEAVE A REPLY

Please enter your comment!
Please enter your name here