Librerie di classi VB e namespace Global con Visual Studio 2012

14 giugno 2013

Dalle raccolte di routine degli anni ’80 ad oggi, la storia delle librerie evolve con l’identico scopo di creare codice riutilizzabile.

Con .NET le raccolte sono diventate librerie di classi, cioè assembly o, più colloquialmente, DLL. Queste librerie raggruppano sotto una unica denominazione molte classi, di solito omogenee tra loro, che con i loro metodi permettono di definire del codice riutilizzabile. I vantaggi sono notevoli:

  • per chi crea le librerie, basti pensare alle librerie di componenti di terze parti create per la vendita senza dover distribuire il codice sorgente;
  • per chi le utilizza, perché semplificano il lavoro, riducono i tempi di sviluppo e di test e aumentano la produttività: il codice delle librerie è già testato e non occorre "reinventare l’acqua calda".

Creare libreria di classi con Visual Studio

Naturalmente anche in Visual Studio 2012 possiamo creare delle librerie di classi..

Visual Studio 2012 fornisce tutti gli strumenti necessari per creare, distribuire e utilizzare librerie di classi. Tra questi strumenti, ora, è compresa anche una nuova funzionalità che è una novità assoluta per Visual Studio: il namespace Global.

In questo articolo parleremo proprio di questo importantissimo namespace, ma prima facciamo un piccolo ripasso sui namespace standard e su quelli personalizzati (definiti dagli sviluppatori). Vedremo poi cosa cambia con l’introduzione del nuovo namespace Global e perché è così importante.

I namespace

I namespace sono concettualmente simili a contenitori e servono a organizzare il codice in unità ben definite. Sono organizzati in modo gerarchico: ciascun namespace può contenere una o più classi, ma anche altri namespace. Ogni namespace di secondo livello può contenere altri namespace e classi e così via, in una struttura gerarchica anche molto complessa e con molti livelli.

È molto importante organizzare bene la gerarchia di namespace e di classi, perché una gerarchia disordinata provoca confusione nello sviluppatore che utilizza la libreria, causando la perdita di tutti i vantaggi che si volevano ottenere.

Anche il .NET Framework è organizzato in questo modo, con moltissimi namespace nidificati a più livelli, come le scatole cinesi. Ogni namespace raggruppa tutte le classi che fanno parte di una specifica categoria: per esempio il namespace System.IO contiene tutte le classi che servono per lavorare con i file, le cartelle e i dischi, con i flussi di input e output e così via.

Qui troviamo anche altri namespace specializzati: Compression, IsolatedStorage, Packaging, Pipes e Ports. A loro volta, questi namespace contengono altre classi associate alla specifica categoria. Per esempio il namespace Compression contiene le classi necessarie a gestire i file compressi.

Il Default namespace

Anche se non ce ne rendiamo conto, nei nostri progetti utilizziamo sempre almeno un namespace: il Root namespace (spazio dei nomi “radice”). Nella documentazione disponibile in rete, in alcuni casi potreste trovare questo elemento denominato anche come Default namespace (Spazio dei nomi predefinito), ma lo potete considerare come sinonimo.

Per verificare che quello che abbiamo affermato è vero, potete aprire qualsiasi soluzione di Visual Studio ed esaminare le proprietà del progetto. Nella scheda Applicazione, infatti, troviamo una proprietà di nome Spazio dei nomi radice:

Figura 1. La proprietà "Spazio dei nomi radice" di un progetto

La proprietà "Spazio dei nomi radice" di un progetto

Come potete vedere in figura, il nome del namespace del progetto è uguale al nome del progetto e dell’assembly, ma potete modificarlo secondo le vostre preferenze (il nome non può iniziare comunque con un carattere numerico).

Definire i namespace nel codice

Chiunque può definire nuovi namespace nei progetti Visual Studio, anche nidificandoli in namespace a più livelli. Per esempio possiamo definire un codice come quello seguente:

Namespace MyNamespace

	Public Class Classe1
	' qui scriviamo il codice della classe Classe1
	End Class

	Namespace MyNamespace2

		Public Class Classe2
		' qui scriviamo il codice della classe Classe2
		End Class

	End Namespace

	Namespace MyNamespace3

		Public Class Classe3
		' qui scriviamo il codice della classe Classe3
		End Class

		Namespace MyNamespace4

			Public Class Classe4
			' qui scriviamo il codice della classe Classe4
			End Class

		End Namespace
	End Namespace
End Namespace

Per accedere alle varie classi dobbiamo utilizzare una sintassi che tenga conto di tutto il "percorso" che è necessario seguire per raggiungere la classe, in modo non molto diverso da quello che si fa normalmente nel file system per indicare un file contenuto in una delle sottocartelle. Per esempio, se vogliamo accedere alla Classe1 possiamo utilizzare il riferimento:

MyNamespace.Classe1

Per accedere alla Classe4, invece, dobbiamo utilizzare il riferimento:

MyNamespace.MyNamespace3.MyNamespace4.Classe4

Poiché i namespace hanno sempre un livello di accesso di tipo Public, possiamo accedere liberamente ai namespace da qualsiasi punto del codice.

Proviamo ora a vedere un esempio con una applicazione di prova.

"Metodo tradizionale" in un’applicazione Visual Basic

Consideriamo come "metodo tradizionale" quello che si è sempre fatto prima dell’introduzione del nuovo namespace Global. In seguito vedremo cosa cambia utilizzando Global.

Dopo aver creato un’applicazione di tipo WPF (che noi abbiamo chiamato MyLibrary_VS2012_01_VB), inseriamo tre caselle di testo (Valore1, Valore2 e Risultato), tre controlli di tipo Label per le descrizioni e due pulsanti (Somma1 e Somma2), disposti come in figura:

Figura 2. La prima applicazione di prova

La prima applicazione di prova

Il codice XAML è il seguente:

<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="Valore1" HorizontalAlignment="Left" VerticalAlignment="Top"
		                          Height="37" TextWrapping="Wrap" Text="0"  
								  Width="180" Margin="140,28,0,0" FontSize="20"/>
		
		<TextBox x:Name="Valore2" HorizontalAlignment="Left" VerticalAlignment="Top"
                                  Height="37" TextWrapping="Wrap" Text="0" Width="180"
								  Margin="140,70,0,0" FontSize="20"/>

		
		<Button x:Name="Somma1" Content="Somma senza Global" HorizontalAlignment="Left" 
		                                                     VerticalAlignment="Top" 
															 Width="275" Margin="45,124,0,0"
															 FontSize="20"/>

		<Button x:Name="Somma2" Content="Somma con Global" HorizontalAlignment="Left"
		                                                   VerticalAlignment="Top"
														   Width="275" Margin="45,160,0,0" 
														   FontSize="20"/>

        <Label Content="Valore 1" HorizontalAlignment="Left" VerticalAlignment="Top" 
		                          Margin="45,24,0,0" FontSize="20"/>

		<Label Content="Valore 2" HorizontalAlignment="Left" VerticalAlignment="Top"
		                          Margin="45,66,0,0" FontSize="20"/>
		
		<Label Content="Risultato" HorizontalAlignment="Left" VerticalAlignment="Top" 
		                           Margin="45,221,0,0" FontSize="20"/>

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

L’obiettivo che ci poniamo è quello di sommare i due valori inseriti nelle caselle di testo e inserire il risultato nella terza casella di testo. Ovviamente è un obiettivo semplice da raggiungere e anche poco interessante: proprio per la semplicità del compito possiamo concentrarci meglio sul vero obiettivo del progetto, cioè una migliore definizione di una libreria di classi.

Aggiungete una classe di nome Class1.vb nel progetto Visual Basic, aprite il file con un doppio clic e inserite il seguente codice:

' Esempio: 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

Questa classe espone una funzione (Somma) che prende due interi di tipo Long come argomenti di ingresso, e ne restituisce la somma. Come abbiamo già specificato, la semplicità della funzione è voluta per non aggiungere un ulteriore livello di complessità. Naturalmente voi potete definire qualsiasi funzione, anche qualcosa di molto complesso.

Dopo aver aggiunto una nuova classe di nome Class2.vb, inserite il seguente codice:

' Esempio: MyLibrary_VS2012_01_VB
Namespace 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

Come potete vedere, Class2 contiene esattamente le stesse istruzioni di Class1, ma in questo caso è inserita nella dichiarazione del namespace Utilities. Questo nome è inventato, per seguire l’esempio potete scegliere lo stesso nome o quello che preferite.

A prima vista, il namespace Utilities dovrebbe essere un namespace di primo livello, ma come vedremo le cose non stanno esattamente in questi termini.

Ora dobbiamo attivare i due pulsanti, in modo che premendoli succeda qualcosa di utile.

Torniamo al file MainWindow.xaml ed eseguiamo un doppio-clic su entrambi i pulsanti, in modo da creare lo schema vuoto dei loro gestori degli eventi Click. Inseriamo quindi il seguente codice:

' Esempio: MyLibrary_VS2012_01_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 MyLibrary_VS2012_01_VB.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 MyLibrary_VS2012_01_VB.Utilities.Class2
			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
End Class

Abbiamo verificato che entrambe le caselle di testo abbiano un valore numerico valido: se entrambi i valori sono validi viene eseguita la somma, se anche un solo valore non è numerico (testo o vuoto) viene visualizzato un messaggio di errore.

I due metodi sono pressoché uguali, tranne per la terza istruzione che rispettivamente si presenta così:

Dim Utilities As New MyLibrary_VS2012_01_VB.Class1

e così:

Dim Utilities As New MyLibrary_VS2012_01_VB.Utilities.Class2

Vedremo in seguito il motive di questa differenza. per ora limitiamoci ad avviare l’applicazione. Dopo aver inserito due valori numerici nelle prime due caselle di testo provate a premere il primo pulsante. Se il codice è scritto correttamente, dovremmo vedere nella terza casella di testo il valore risultante dalla somma dei due valori inseriti.

Lo stesso avverrà premendo il secondo pulsante, a dimostrazione che i due metodi sono assolutamente equivalenti.

Notiamo, però, che nel codice abbiamo dovuto inserire un riferimento esplicito allo Spazio dei nomi radice (MyLibrary_VS2012_01_VB). Nel secondo caso, poi, vediamo che il namespace Utilities dipende dallo spazio dei nomi radice, cioè è un namespace di secondo livello, mentre noi volevamo che questo diventasse un namespace principale, cioè un namespace di primo livello.

Nella figura seguente osserviamo la posizione delle classi Class1 e Class2 nella gerarchia di classi dell’applicazione:

Figura 3. Gerarchia delle classi nella finestra Visualizzazione classi

Gerarchia delle classi nella finestra Visualizzazione classi

Continuiamo ora con il namespace Global.

Se vuoi aggiornamenti su Librerie di classi VB e namespace Global con Visual Studio 2012 inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Librerie di classi VB e namespace Global con Visual Studio 2012

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy