Sei sulla pagina 1di 68

ED I T O R I A L E online.infomedia.

it
n. 65 - settembre/ottobre 2005
bimestrale - anno undicesimo

Direttore Responsabile
Marialetizia Mari (mmari@infomedia.it)
Direttore Esecutivo

Il futuro Francesco Balena (fbalena@infomedia.it)


Managing Editor

dei linguaggi .NET


Renzo Boni (rboni@infomedia.it)
Collaboratori
Maurizio Codogno
Stefano Corti
Emanuele DelBono

C ome potete leggere in questo numero della rivista, le novità


alla PDC 2005 sono tante e tutte ben corpose. Io quest’anno
non ho partecipato, quindi posso al massimo ragionare sul
materiale messo a disposizione sul sito Microsoft e non potevo
certo resistere alla curiosità di capire in che direzione stanno an-
Raffaele Di Natale
Fabio Fabozzi
Claudio Maccari
Angelo Ossola
Fabio Perrone
Paolo Pialorsi
Francesco Quaratino
dando Visual Basic e C#. Così mi sono tenuto un pomeriggio da Stefano Sanna
parte per dare un’occhiata agli articoli già disponibili. Lorenzo Vandoni

Alla fine del pomeriggio mi sono ritrovato con sentimenti ambi-


valenti. Da una parte c’era l’innegabile soddisfazione di vedere che
il Visual Basic continua a colmare il gap rispetto al C# – a dispetto delle mille cassandre
a cui piace etichettare il VB come un linguaggio di seconda scelta.
Direzione
Natale Fino (nfino@infomedia.it)
A parte queste e altre (piccole) piacevolezze, devo però dire che in generale quello che ho
letto non mi ha affatto entusiasmato. La novità principale di VB9 e C#3 è il supporto di
Marketing & Advertising
Segreteria: 0587/736460
Linq, una specie di embedded SQL che permette di immergere query SQL direttamente marketing@infomedia.it
nel codice. In teoria, Linq dovrebbe promuovere una più stretta integrazione tra i database
Amministrazione
relazionali e i modelli ad oggetti (intrinsecamente gerarchici) costruiti nella propria appli- Sara Mattei
cazione. In pratica, però, questa integrazione non si può affatto dare per scontata. Alcuni (amministrazione@infomedia.it)
progetti simili – primo tra tutti, ObjectSpaces – sono falliti oppure comunque non hanno Grafica
mai conquistato il cuore degli sviluppatori, che continuano a produrre ottime applicazioni Manola Greco (mgreco@infomedia.it)
gestionali senza bisogno di queste infrastrutture (o sovrastrutture, se preferite). L’altro
Technical Book
punto importante è che se Linq non offrirà prestazioni identiche a quelle offerte da SQL
Lisa Vanni (book@infomedia.it)
tradizionale, nessuno vorrai mai utilizzarlo.
Segreteria
Enrica Nassi
Il problema, comunque, non è tanto quello di aggiungere feature che poi nessuno userà (info@infomedia.it)
realmente, quanto il fatto che il supporto per Linq costringe ad altre “novità”, ad esempio
gli anonymous types. E a loro volta, gli anonymous types richiedono di rilassare la sintassi
di alcune istruzioni. Ad esempio, sarà possibile dichiarare una variabile senza la clausola Stampa
As, lasciando al compilatore il compito di determinare il tipo necessario. Con tanti saluti TIPOLITOGRAFIA PETRUZZI
Citta’ di Castello (PG)
alla leggibilità del codice!
Ufficio Abbonamenti
Il discorso è complesso e non è certo adatto alla paginetta che questo editoriale mi Tel. 0587/736460 - Fax 0587/732232
concede. La stessa Microsoft ha dichiarato che questa pre-release serve soprattutto a e-mail: abbonamenti@infomedia.it
raccogliere le impressioni della comunità degli sviluppatori. Ho scritto qualcosa sul mio www.infomedia.it
blog e sicuramente tornerò sull’argomento man mano che altre novità diventeranno Gruppo Editoriale Infomedia srl
disponibili, e sarà interessante confrontare le opinioni di tutti coloro che usano questi Via Valdera P., 116 - 56038 Ponsacco (PI) Italia
strumenti “sul campo”. Tel. 0587/736460 - Fax 0587/732232
red_vbj@infomedia.it
Sito Web www.infomedia.it

Manoscritti e foto originali anche se non pubblicati,


Francesco Balena non si restituiscono. È vietata la riproduzione
anche parziale di testi e immagini.
fbalena@dotnet2themax.it
www.dotnet2themax.it/blog Si prega di inviare i comunicati stampa e gli inviti stampa per
la redazione all’indirizzo: comunicatistampa@infomedia.it
Visual Basic Journal è una rivista di
Gruppo Editoriale Infomedia S.r.l. Via Valdera P, 116 Ponsacco - Pisa.
Registrazione presso il Tribunale di Pisa n. 20/1999
4 N. 65 - Settembre/Ottobre 2005 VBJ
SOMMARIO
S E T T E M B R E / OT TO B R E

N.65
SPECIALE

Reportage da PDC 2005 8


Dall’11 al 16 settembre 2005 si è tenuta a Los Angeles la Professional Developer Conference 2005, orga-
nizzata da Microsoft Corporation.
a cura di DevLeap

MULTIMEDIA
Controlli multimediali in Visual Basic 6 20
Non capita spesso di realizzare software dai contenuti multimediali. Questo articolo illustra le modalità di gestione di elementi
multimediali in VB6: non sarà forse molto originale, ma di sicuro se ne potrà apprezzare la valenza evocativa per coloro che
già sanno ed educativa per coloro che ancora non sanno.
di Fabio Fabozzi

APPLICAZIONI
Controllo Remoto in Visual Basic .NET (seconda puntata) 26
SQL Server 2005 rappresenta una grande evoluzione nella gestione di database. Vediamo come l’integrazione con il
framework .NET possa migliorare la vita degli sviluppatori e dei DBA.
di Stefano Corti

DATABASE
Supporto XML in SQL Server 2005 33
Sql Server 2005 introduce il tipo di dato nativo XML per trattare documenti e frammenti XML, insieme a metodi
specifici per interrogare e modificarne il contenuto. XQuery è il linguaggio implementato per le interrogazione dei
dati XML attraverso i nuovi metodi di interrogazione.
di Francesco Quaratino

6 VBJ N. 65 - Settembre/Ottobre 2005


RUBRICHE

Editoriale 4
.NET Tools 52
Libri 65

.NET
Sviluppare Servizi Windows con .NET 38
In passato scrivere Servizi Windows richiedeva la conoscenza del C o del C++ ma con l’avvento del framework .NET e dei
suoi nuovi linguaggi C# e VB.NET, lo sviluppo di questo tipo di applicazioni non è mai stato così semplice. Vediamo come
scriverli, installarli e testarli.
di Emanuele Delbono e Claudio Maccari

SOAP Messaging con WSE 45


Vediamo le principali caratteristiche di Microsoft Web Services Enhancements dal punto di vista del SOAP Messaging.
di Paolo Pialorsi

SOFTWARE ENGINEERING
I design pattern più famosi implementati in VB.NET (quarta puntata)
Il pattern Adapter suggerisce come modificare una classe server in modo da adattarsi all’interfaccia richiesta da altre
classi client.
60
di Lorenzo Vandoni

Codice allegato
All’indirizzo ftp.infomedia.it/pub/VBJ sono liberamente scaricabili tutti i listati relativi agli articoli pubblicati.
La presenza di questa immagine indica l’ulteriore disponibilità, allo stesso indirizzo, di un progetto software
relativo all’articolo in cui l’immagine è inserita. Il nome identifica la cartella sul sito ftp.

N. 65 - Settembre/Ottobre 2005 VBJ 7


SPECIALE

Reportage da PDC 2005


Dall’11 al 16 settembre 2005 si è tenuta a Los Angeles la Professional Develo-
per Conference 2005, organizzata da Microsoft Corporation.

a cura di DevLeap

all’11 al 16 settembre 2005 si è tenuta a Los Grande rilievo hanno avuto an-

D Angeles la Professional Developer Conferen-


ce 2005 (PDC05). Si tratta di un evento tec-
nico organizzato da Microsoft Corporation e rivolto
che la versione 3.0 del linguaggio
C# e la tecnologia .NET Langua-
ge Integrated Query (LINQ). An-
a programmatori che utilizzano le tecnologie di Re- che ATLAS, estensione del mo-
dmond per lo sviluppo delle proprie applicazioni. È tore di ASP.NET per supportare
un evento che non ha una cadenza fissa, ma che vie- il tanto discusso AJAX (Asyncro-
ne organizzato solo quando Microsoft ha qualcosa di nous Javascript And XML), si è
particolarmente interessante da annunciare agli svi- fatto spazio fra le numerose ses-
luppatori. Quest’anno gli argomenti di maggior rilievo sioni dell’evento. Infine per la
sono stati l’imminente rilascio del .NET Framework parte sistemi sono stati presenta-
2.0, accompagnato da SQL Server 2005 e BizTalk Ser- ti Windows Vista e Windows Lon-
ver 2006, ma anche e soprattutto l’annuncio di nuove ghorn Server. Di seguito parlere-
tecnologie e prodotti che vedranno la luce nei prossi- mo di alcuni di questi argomenti
mi due anni. Tra questi possiamo sicuramente citare in maggiore dettaglio.
WinFX, che rappresenta il framework di base per le
applicazioni business dei prossimi anni. A oggi Win- Windows Workflow
FX è rappresentato dall’insieme di Windows Presen- Foundation
tation Foundation (WPF, conosciuto con il nome in co- Da alcuni mesi ormai si parlava
dice “Avalon”) per la gestione dell’interfaccia utente, in modo informale di un possibile
Windows Communication Foundation (WCF, nome in rilascio, da parte di Microsoft, di
codice “Indigo”) per lo strato di comunicazione e ser- un motore di workflow integrato
vizi SOAP e Windows Workflow Foundation (WWF, nel sistema operativo Windows e
sconosciuto ai più sino a PDC05) per la gestione dei distribuito gratuitamente agli
processi e flussi aziendali. Un altro argomento che ha utenti del sistema stesso. In que-
avuto il suo peso è l’anteprima della prossima versio- sta PDC è stato definitivamente
ne di Microsoft Office, ormai giunto alla versione 12, svelato il progetto Windows Work-
e di Windows SharePoint Services 3.0. flow Foundation (WWF), al quale
pare che stia lavorando da tempo
un gruppo costituito anche da al-
cuni membri del team di BizTalk
Server. Il progetto dovrebbe vede-
re la luce nella seconda metà del
Paolo Pialorsi è un consulente e autore specializzato nello prossimo anno e pare che sarà
sviluppo di Web Service e soluzioni Web con il Framework
.NET di Microsoft. Lavora nell’omonima società Pialorsi Sistemi offerto gratuitamente, un po’
S.r.l. e fa parte del gruppo DevLeap. Può essere contattato via come è stato per Windows Sha-
email: paolo@devleap.it. Paolo mantiene un blog all’indirizzo: repoint Services rispetto a Win-
http://blogs.devleap.com/paolo/ .
dows Server 2003. Si tratta di un

8 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

framework applicativo sviluppato in codice ma-


naged .NET e pensato per gestire/creare work-
flow che interagiscono con i vari servizi e pro-
dotti software Microsoft e con applicazioni di
terze parti. WWF prevede un’architettura che
si appoggia a un motore di base, in grado di ge-
stire eventi, timer, flussi e relativi stati. Questi
sono poi legati all’esecuzione e all’esito di attivi-
tà, che non sono altro che classi .NET; per i casi
di uso più ricorrente (invio email, attesa compi-
lazione form, approvazione/non approvazione di
un documento, chiamata a un Web Service, ecc.)
potremo contare su classi già presenti nel pro-
dotto, mentre per tutti gli altri si possono crea-
re classi in appositi progetti .NET, che verranno
configurati in WWF. Il motore di WWF prevede
la possibilità di realizzare flussi automatici o che
interagiscono con l’utente finale. Nel secondo
caso è possibile utilizzare vari strumenti di inte-
razione con l’utente come: Office InfoPath, form
e email con voting button di Outlook, pagine ad • Disegno del flusso con la prossima versione
hoc in Windows Sharepoint Services, Web Servi- di FrontPage (quella che sarà presente in Of-
ce; ecc. L’hosting dei flussi è altrettanto variabi- fice 12 e che non ha quasi più niente a che
le e dipende dal particolare tipo di implementa- vedere con FrontPage attuale) tramite l’uti-
zione che si vuole realizzare. Al minimo possia- lizzo di un wizard grafico su più passi;
mo creare un’applicazione Console, comandando • Definizione del flusso tramite Visual Studio
da codice il flusso, oppure possiamo definire ap- 2005 (qualsiasi versione, anche le Express
plicazioni Windows Forms o Web, eventualmen- gratuite) utilizzando un apposito designer,
te utilizzando in questo secondo caso il motore integrato con l’IDE. In questo caso è pre-
di Sharepoint 3.0, come vero host dei flussi. Lo vista la scrittura di piccole porzioni di co-
storage dei flussi e dei loro stati di avanzamen- dice, associate ai singoli eventi del flusso.
to è personalizzabile e configurabile. Possiamo
appoggiarci a semplici flussi in memoria, sen- Tutti i flussi, a prescindere da come ven-
za alcun tipo di persistenza, oppure è possibile gono disegnati, sono rappresentabili e/o
serializzare i flussi in file XML su disco (o altri esportabili in formato XOML, una gram-
storage). Per scenari più complessi, dove deve matica XML pensata per descrivere stati,
essere garantito un elevato livello di affidabili- azioni e regole del flusso. In questo modo
tà, c’è la possibilità di utilizzare Microsoft SQL potremmo anche definire un flusso a parti-
Server come storage permanente, transaziona- re da un XML “grezzo” e da una trasforma-
le e sicuro dei dati di WWF. Operativamente la zione XSLT. Si possono definire flussi a fasi
creazione di un flusso, per quanto si è visto in singole e con stati finiti, oppure si possono
una prima versione beta, è realizzabile utiliz- creare flussi multi-attività e a stati variabili.
zando una delle seguenti strade: Dal momento che parte del motore di WWF
è stato “importato” e adattato dal designer
• Sviluppo di codice .NET su misura. Soluzio- di orchestration di BizTalk Server, non ven-
ne molto versatile, ma relativamente impe- gono meno alcune delle funzionalità chiave
gnativa, oltre a richiedere uno sviluppatore di BizTalk, come la possibilità di interagire
.NET per poterla realizzare; con Web Service esterni e di svolgere atti-

N. 65 - Settembre/Ottobre 2005 VBJ 9


SPECIALE

vità transazionali e long running, con even- dio delle migliori modalità di interazione con i
tuali compensating transaction. Non a caso singoli comandi, per arrivare ad avere qualco-
si è lasciato intendere che la prossima ver- sa che sembra semplice da usare quanto una
sione di BizTalk Server, dopo l’imminente calcolatrice. Sembra facile, ma non lo è assolu-
versione 2006, possa utilizzare direttamente tamente. Dal punto di vista funzionale, Office
WWF per la definizione dei suoi flussi e or- 12 ha diversi “pilastri”: integrazione comple-
chestration. ta con SharePoint v3, integrazione di funzioni
di WorkFlow, componenti Office lato server e
Microsoft Office 12 funzioni di visualizzazione dati avanzate (Bu-
Office 12 sarà la release con le maggiori no- siness Intelligence) in Excel.
vità percepibili dall’utente rispetto alla ver- Partiamo dai componenti Office lato server:
sione precedente sin dai tempi di Office 97. l’idea è più o meno quella di consentire a un
Il motivo è che l’interfaccia utente cambia ra- utente di “pubblicare” un foglio Excel su un
dicalmente: via i menu, via le toolbar, avremo server producendo pagine HTML che conten-
un nuovo elemento, il Ribbon, che agisce in gono il risultato di un foglio Excel, aggiornato
modo contestuale alle azioni dell’utente. Ap- in base ai dati letti dinamicamente dal server.
parentemente un Ribbon è una nuova forma In altre parole, se si crea un foglio Excel che
di toolbar, in realtà ci sono regole ben precise presenta il totale delle vendite diviso per ca-
su ciò che può contenere, su cosa può presen- tegoria di articolo, estraendo tali informazioni
tare e come deve interagire con l’utente. Tec- da un database relazionale o multidimensiona-
nicamente un Ribbon è un contenitore di Tab, le (Analysis Services), pubblicando il foglio sul
ciascuno dei quali può avere più Chunk che server si ottiene una pagina HTML con i dati
a loro volta contengono oggetti di vario tipo aggiornati al momento della richiesta (e non
(Button, Label, EditBox, CheckBox, Gallery e solo della pubblicazione!); tutto questo avvie-
anche Menu). L’impatto, vedendo una foto, è ne senza avere sul server un’istanza di Excel,
di estrema diffidenza (perché mai hanno cam- come potrebbe avvenire oggi (ma dal punto di
biato tutto?). Ma l’esperienza d’uso è incredi- vista della scalabilità si tratta di un incubo, si
bile: fondamentalmente Office 12 ha gli stes- mette su un server un componente pensato
si comandi di controllo del layout (in Word ed per un desktop client dedicato). Questo porta
Excel) di Office 2003 (e in gran parte anche di a un mondo dove gli utenti possono definire
Office XP, 2000 e 97!) ma semplicemente... mol- dei report da pubblicare sulla Intranet azien-
ti non sanno nemmeno dove cercarli. Sembra dale usando il loro amato foglio Excel. Questa
di usare un prodotto completamente nuovo, le sola funzione vale oro. La funzione di workflow
funzionalità sono proposte esattamente quan- (implementata basandosi su WWF) introduce la
do servono e in maniera intuitiva, con poche possibilità di definire processi di gestione do-
(spesso nessuna) dialog box. cumentale, ma non solo: grazie all’estendibili-
Ci si può chiedere perché si parli di interfac- tà del WWF è possibile introdurre propri com-
cia utente di un prodotto come Office in una ponenti nel workflow e personalizzare alcune
rivista di programmazione: il punto è che Of- parti di tutto il processo. Anche qui, per il pro-
fice ha sempre stabilito le linee guida di in- grammatore diventa banale creare l’infrastrut-
terfaccia utente per le applicazioni “cool” in tura di workflow (quella c’è già) e ci si può con-
Windows. Non è detto che il modello di Office centrare sugli aspetti prettamente funzionali
12 sia sensato per un’applicazione con 10 fun- delle attività da svolgere. Chi ha sudato anni
zioni in tutto, ma molti gestionali potrebbero di lavoro su questi temi sa quanto possa esse-
trarne enormi vantaggi in termini di semplici- re decisiva una funzionalità del genere in am-
tà d’uso. Ma avere uno strumento non significa bito aziendale: con Office 12 e Windows Vista
essere in grado di usarlo proficuamente: die- sarà addirittura pervasiva. SharePoint v3 è il
tro Office 12 devono esserci anni-uomo di stu- collante tra WWF, Office 12 e componenti Offi-

10 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

ce lato server e vi dedichiamo un’intera sezio- cade oggi. Avremo il “cestino” per recuperare i
ne dell’articolo, poco più avanti. Excel 12 è il documenti eventualmente cancellati per errore.
nuovo client di riferimento per accedere ai dati Potremo definire gestori di eventi multipli sul-
aziendali. Supporta dati relazionali e multidi- le liste, anziché doverci adattare ad averne al
mensionali, offre finalmente tutte le funziona- massimo uno solo. I gestori di eventi saranno
lità di Analysis Services 2005 e Analysis Servi- configurabili anche sulle liste non documenta-
ces 2000 (Excel 2003 non consente di sfruttare li. Per esempio potremo configurare un nostro
appieno le capacità di Analysis Services 2000). handler personalizzato che ci invii una email
Ma non basta, Excel 12 integra anche funziona- ogni qual volta venga creato un contatto nella
lità avanzate di visualizzazione dei dati (oltre rubrica condivisa aziendale. Proprio nell’ottica
a tabelle pivot e grafici, per capirci) che deri- della gestione dei dati aziendali e della creazio-
vano dall’esperienza di Microsoft Data Analy- ne di un portale aziendale basato su Sharepoint,
zer (il team di sviluppo di quel prodotto è sta- sarà possibile collegare gli item di una lista, per
to inglobato in quello di Excel già dal lontano esempio la lista di contatti, con i dati presen-
2001). Purtroppo su questa parte c’è ancora un ti in database esterni, come potrebbe essere il
po’ di riservatezza e queste funzioni non sono database del sistema ERP aziendale.
ancora state mostrate al pubblico, ma non do- Immaginate la comodità di vedere dal por-
vrebbe mancare molto per qualche anteprima. tale l’elenco dei clienti, con i loro recapiti, ma
Note per chi sviluppa soluzioni con/per Office: anche con le loro posizioni aperte (saldo dare/
Office 12 sarà anche l’occasione per una nuo- avere) direttamente lette dall’ERP e aggiorna-
va versione, la 3.0, di Visual Studio Tools for te in tempo reale, potendo passare con un cli-
Office; inoltre vedremo l’erede di VBA (Visual ck alla lista di documenti (fatture, bolle, email,
Basic for Applications) che si chiamerà VSTA fax) relative al cliente. Se poi vorremo gestire
(Visual Studio Tools for Applications), che con- procedure aziendali, per esempio legate all’in-
sentirà di scrivere le macro di Office in codice serimento di un ordine o al caricamento di un
.NET. Office 12 al momento è ancora sotto stret- documento da approvare, potremo attivare uno
tissimi NDA (Non Disclosure Agreement) e la dei workflow predefiniti e “classici” già presenti
beta non è ancora aperta al pubblico. La Beta in WSS 3.0, oppure creare i nostri con WWF, per
1 sarà disponibile entro fine anno (si ipotizza poi collegarli a Sharepoint. Per i programmatori
per i primi di dicembre) e il prodotto dovreb- che hanno l’esigenza di estendere il motore di
be essere rilasciato nel secondo semestre 2006. WSS, un’altra novità interessante è la possibi-
Il commento pressoché unanime che abbiamo lità di creare tipi di campi personalizzati, senza
raccolto in chi ha visto Office 12 all’operà si può più essere vincolati al solo set di dati predefini-
riassumere più o meno così: si venderà da solo. to. Se dovessimo trovare a oggi una carenza o
Vedremo se si tratta di analisi accurate o è solo un punto debole in WSS 3.0, potremmo indica-
il frutto dell’entusiasmo per la novità. re l’assenza di supporto nativo per device mo-
bili. Tutto il resto di necessario, rispetto anche
Windows Sharepoint Services 3.0 alla nostra esperienza diretta con il prodotto in
Windows Sharepoint Services 3.0 ha destato versione attuale, è ormai presente nella prossi-
notevole interesse. Volendo riassumere in uno ma release. Il giorno in cui Microsoft dovesse
slogan le novità di WSS 3.0 si potrebbe dire: rendere accessibile WSS 3.0 a client Windows
avrà tutto quello che oggi manca a WSS 2.0! Mobile (che ormai montano “di serie” il .NET
Volendo entrare nel dettaglio, le document li- Compact Framework), quello sarebbe il giorno
brary, cioè le cartelle destinate a contenere i della svolta, in cui tutte le aziende con gestio-
documenti, saranno molto più configurabili di ne informatica delle procedure passerebbero a
quanto lo siano nella versione 2.0. Per esempio Sharepoint!
avremo la possibilità di definire permessi sui Non ultimo troveremo una rinnovata interfac-
singoli file e non solo sulle cartelle, come ac- cia utente, in linea con l’evoluzione che anche

N. 65 - Settembre/Ottobre 2005 VBJ 11


SPECIALE

Office 12 subirà. Il rilascio di WSS 3.0 è previsto utilizzata un’istanza di una classe OtherClass
in concomitanza con quello di Office 12, indi- che non presenta il metodo DoSomething nel-
cativamente dopo la prossima estate 2006. la sua definizione, ma sulla quale abbiamo co-
munque l’illusione di poterlo invocare, proprio
C# 3.0 grazie agli Extension Methods, che rendono il
Per gli sviluppatori .NET appassionati del metodo DoSomething di MyExtension disponi-
Framework e di C#, le sessioni sul futuro bile su tutti gli altri tipi, purché venga importa-
C# 3.0 e sulla tecnologia Language Integra- to, tramite la parola chiave using, il namespace
ted Query (Linq) sono state un cibo impagabi- che contiene MyExtension.
le per la mente. Quando parliamo di prossima Un’altra comoda aggiunta al linguaggio sono
versione del linguaggio C# non ci riferiamo i “Type Initializers” e i “Collection Initializers”,
a quella che uscirà sul mercato a novembre, che consentono di inizializzare un oggetto sen-
con il lancio di .NET 2.0 e Visual Studio 2005, za passare attraverso la valorizzazione manuale
bensì a quella ancora successiva, indicativa- di tutte le sue proprietà, ma nemmeno doven-
mente prevista per il 2007/2008. La prossima do definire una serie di costruttori ad hoc per
versione del linguaggio C# sarà arricchita da le varie configurazioni da inizializzare. Pensia-
una serie di funzionalità accessorie, pensate mo al caso seguente:
per semplificare e rendere più rapida la scrit-
tura del codice, così come per supportare Linq, C# 2.0
di cui parleremo nella prossima sezione. Par- public class Cliente
tiamo dalle modifiche al linguaggio: sarà pos- {
sibile estendere “virtualmente” tipi già defi- public String Nome;
niti, come se venissero definiti nuovi meto- public String Cognome;
di di istanza di classi già dichiarate. Questo }
comportamento “apparente” si otterrà tramite
metodi statici di altre classi (sempre statiche) // ...
che estendono il tipo definito al primo para-
metro, decorato con il modificatore this. Cliente c = new Cliente();
c.Nome = “Mario”;
C# 3.0 c.Cognome = “Rossi”;
public static class MyExtension
{ Se volessimo inizializzare in modo più rapi-
public static String DoSomething(this Int32 param1, do le istanze di Cliente dovremmo creare co-
String param2) {...}; struttori appositi e fornire i valori di Nome e
} Cognome. Con C# 3.0 e i Type Initializers si
potrà scrivere:
public class OtherClass
{ C# 3.0
public String Name; Cliente c = new Cliente {Nome = “Mario”, Cognome = “Rossi”};
}
senza avere bisogno di un costruttore dedi-
OtherClass oc = new OtherClass(); cato. Nel caso delle collezioni l’idea è la stes-
String result = oc.DoSomething(10, oc.Name); sa, ma si inizializzano elenchi di istanze:

In questo breve esempio è definita una classe C# 3.0


statica di nome MyExtension, con un metodo List<Cliente> clienti = new List<Cliente> {new Cliente
altrettanto statico e il primo parametro esteso {Nome = “Mario”, Cognome = “Rossi”}, new Cliente {Nome =
con l’informazione “this”. Nel codice poi viene “Luca”, Cognome = “Bianchi”}};

12 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

Esistono poi gli “Anonymous Types”. Si trat- ne di ClienteSemplice, in quanto viene dedot-
ta di tipi creati automaticamente dal compi- to dai nomi delle proprietà di c (tipo Cliente)
latore, generalmente utilizzati per il passag- passate come parametri. Arriviamo dunque a
gio di dati o la creazione di sottoinsiemi di questa versione intermedia di codice:
tipi esistenti. Ripensiamo ancora alla classe
Cliente, però così definita: C# 3.0
Cliente c = new Cliente {Nome = “Mario”, Cognome =
C# 3.0 “Rossi”, Telefono = “030-123456”};
public class Cliente var cs = new ClienteSemplice {c.Nome, c.Cognome};
{
public String Nome; E se dessimo per scontato anche il tipo Clien-
public String Cognome; teSemplice? In C# 3.0 possiamo definire im-
public String Telefono; plicitamente un tipo deducendone la dichia-
public List<Indirizzo> Indirizzi; razione dai parametri passati nel Type Initiali-
} zer; quindi, per creare un tipo che sia sottoin-
sieme di Cliente, possiamo scrivere:
public class ClienteSemplice
{ C# 3.0
public String Nome; Cliente c = new Cliente {Nome = “Mario”, Cognome =
public String Cognome; “Rossi”, Telefono = “030-123456”};
} var cs = new {c.Nome, c.Cognome};

Ci sono situazioni in cui si vogliono utilizzare Il compilatore C# 3.0 creerà per noi, in fase
solo Nome e Cognome di un oggetto Cliente, di compilazione, un tipo .NET con la struttura
appoggiandosi magari a un tipo intermedio, più da noi desiderata e lo farà diventare il tipo del-
snello, come è il ClienteSemplice. Con la se- la variabile cs: nei fatti, var viene sostituito con
guente sintassi, che utilizza i Type Initializers, il nome del tipo (il compilatore ne genera uno
possiamo creare l’oggetto “più piccolo”: automaticamente). L’aspetto interessante è che
anche se apparentemente si sta utilizzando un
C# 3.0 linguaggio “dinamico”, dove non sembra esserci
Cliente c = new Cliente {Nome = “Mario”, Cognome = un continuo controllo sui tipi a livello dichiara-
“Rossi”, Telefono = “030-123456”}; tivo, il compilatore lavora sempre in modo for-
ClienteSemplice cs = new ClienteSemplice {Nome = c.Nome, temente tipizzato, liberando il programmatore
Cognome = c.Cognome}; dalla necessità di inventare tipi “di servizio” per
operazioni di manipolazione dei dati. Sempre a
Guardando questo codice ci rendiamo conto livello sintattico sono state aggiunte le “Lamb-
che una serie di informazioni possono essere da Expression”. Prese dal mondo accademico
date per scontate, ricavandole dal contesto. Il e della ricerca, le Lambda Expression servo-
fatto che il risultato di una nuova istanza della no principalmente per passare porzioni di co-
classe ClienteSemplice sia memorizzato in un dice come parametro ad altre procedure. Par-
oggetto di tipo ClienteSemplice è prassi comu- tiamo da un esempio più completo:
ne. In C# 3.0 hanno coniato la parola chiave
var (da non confondersi né con il Variant di VB C# 3.0
e COM, né con var di Java o Javascript!) che string[] nomiDevLeap = { “Luca”, “Silvano”, “Marco”,
permette di lasciare al compilatore l’onere di “Paolo”, “Roberto” };
ricavare, in modo implicito, il tipo che risulta var nomiLunghi = from n in nomiDevLeap
dalla new. Si può inoltre omettere il nome delle where n.Length > 5
proprietà Nome e Cognome nell’inizializzazio- orderby n

N. 65 - Settembre/Ottobre 2005 VBJ 13


SPECIALE

select n.ToUpper() SQL Server, ma è possibile creare estensio-


ni al motore Linq, per supportare altri tipi di
foreach ( string s in nomiLunghi ) { persistenza. Linq permette di vedere i dati a
Console.WriteLine( s ); livello di codice come insieme di oggetti con
} proprietà, anziché come tabelle con campi,
però mantenendo un legame con il substra-
In pratica questo codice è esattamente iden- to, in modo tale da poter replicare sul data-
tico al seguente: base le modifiche apportate al modello ad og-
getti. Un aspetto interessante è la possibilità
C# 3.0 di differire la risoluzione delle espressioni di
string[] nomiDevLeap = { “Luca”, “Silvano”, “Marco”, query. Ciò avviene con varie tecniche, anche
“Paolo”, “Roberto” }; in funzione del punto in cui risiedono i dati.
IEnumerable<string> nomiLunghi = nomiDevLeap Nel caso si voglia interrogare un db relazio-
.Where( n => n.Length > 5 ) nale, è possibile convertire la sintassi Linq
.OrderBy( n => n ) in unità minime, dette Expression, organiz-
.Select( n => n.ToUpper() ); zate in Expression Tree. In pratica le Lamb-
da Expression, anziché essere eseguite diret-
foreach ( string s in nomiLunghi ) { tamente, sono convertite in un “piano di ese-
Console.WriteLine( s ); cuzione” definito da questi Expression Tree,
} che a loro volta sono poi convertiti in relative
sintassi SQL nel momento in cui sia neces-
In questo codice i metodi Where, OrderBy e sario accedere al database esterno. Il vantag-
Select sono Extension Methods che lavorano gio di questo approccio è che si può interro-
sull’array di stringhe nomiDevLeap e che ese- gare un database o uno storage in generale,
guono al loro interno, tramite delegate, il co- appoggiandosi a modelli a oggetti fortemen-
dice che segue il simbolo =>, cioè la Lamb- te tipizzati, ma anche facilmente collegati alla
da Expression. Tutte queste novità sintattiche base dati reale. Avere un modello ad oggetti
sono dovute sia alla volontà di semplificare la fortemente tipizzato per gestire una base dati
scrittura del codice, sia per supportare Linq. vuol dire evitare potenziali problemi e avere
Come si può intuire dal codice, Linq fa anche regole di validazione sui dati molto più rigi-
un grande uso dei generics sfruttando però le de. In pratica uno dei possibili utilizzi di Linq
Lambda Expression anziché i metodi anonimi è quello di creare un O/R mapper, cioè uno
(come avviene spesso nelle librerie di .NET 2.0, strato che astrae un modello relazionale in
si pensi alla List<T>.FindAll) per sintetizzare un modello a oggetti. In realtà questo è solo
ancora di più il codice. uno degli usi possibili, precisamente DLinq,
ma Linq consente di ottenere anche altri ri-
LINQ sultati, come poter manipolare una struttura
Il .NET Language Integrated Query è un dati XML attraverso comandi simili a SQL
progetto innovativo, che prevede l’estensio- (XLinq). Le attuali implementazioni di Linq
ne del linguaggio C# (ma anche di VB e al- sono DLinq per accedere a basi dati relazio-
tri linguaggi .NET che lo vogliano supporta- nali (al momento solo SQL Server o Access)
re) per potere scrivere all’interno del codice e XLinq per accedere a fonti dati XML. Bi-
query rivolte a una struttura dati generica con sogna però ricordare che si tratta solo di una
una sintassi che sia ancora codice .NET, ma Technical Preview, è evidente la possibile (e in
simile al codice SQL che scriviamo oggi per parte già realizzata) integrazione con WinFS e
i database relazionali, il tutto senza modifica- soprattutto è importante notare come l’archi-
re il motore del CLR. La base dati può essere tettura sia completamente aperta e consenta
in memoria, su un file XML o su un database l’introduzione “indolore” di nuove estensioni

14 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

(dal supporto di altri database per DLinq al- while (dr.Read())


l’implementazione di astrazioni diverse o al- {
ternative allo stesso DLinq). Client cli = new Cliente();
DLinq, come ogni O/R mapper, nasce per ren- cli.Nome = dr.GetString(nomeOrdinal);
dere più “semplice” l’accesso a strutture dati cli.Cognome = dr.GetString(cognomeOrdinal);
memorizzate in database relazionali da parte listaClienti.Add(cli);
di un linguaggo a oggetti. Qual è il problema }
oggi nell’accesso ai database? Non ci sono pro- }
blemi operativi o limitazioni, ma bisogna con-
siderare che verso il database si passano strin- Utilizzando DLinq il codice diventa qualco-
ghe (anche quando usiamo stored procedure) sa di simile a questo
e vengono restituite “cose” tabellari; nel 99%
dei progetti che seguiamo questi dati tabella- DLinq
ri vengono poi convertiti dal codice del Data Table<Customers> clienti = db.Customers;
Access Layer in oggetti e collezioni di ogget- Var contatti = from c in clienti where c.Provincia == “FI”
ti. L’obiettivo di DLinq è semplificare questa select new {c.Nome, c.Cognome}
fase sia nell’estrazione dei dati, che nell’ag-
giornamento degli stessi e nello stesso tem- Oltre alla semplicità del codice, è bene notare
po semplificare l’intercettazione degli errori come un compilatore possa essere d’aiuto su
più comuni di “digitazione”: oggi non esistono oggetti tipizzati, intercettando errori sui nomi
compilatori in grado di indicare se è sbagliato dei campi, sulla loro tipologia e così via.
il nome della stored procedure o di un para- Per descrivere il mapping fra proprietà del-
metro oppure di un campo da estrarre. le classi e entità presenti nel database vengo-
Vediamo un esempio partendo dal classico no utilizzati attributi sulla classe e sulle pro-
codice C# 2.0 (in questo esempio semplifica- prietà esposte e non file XML come avveniva
to e senza gestione eccezioni) nel “compianto” progetto ObjectSpaces di cui
DLinq riprende le idee di base.
DAL e C# 2.0 L’uso degli attributi (generabili automatica-
SqlConnection conn = new SqlConnection(); mente con un apposito tool che analizza la
SqlCommand cmd = new SqlCommand(conn); struttura di un database) è stato oggetto di
cmd.CommandText = ”spListClienti”; contestazioni da parte di molti sviluppatori,
cmd.CommandType = CommandType.StoredProcedure; ma la filosofia attuale è di mantenere DLinq
il più semplice possibile; comunque l’ultima
SqlParameter par = new SqlParameter(); parola su questi aspetti implementativi non è
par.ParameterName = “@IdProvincia”; ancora stata scritta, anzi. Oggi Linq è un “fe-
par.SqlDbType = SqlDbType.NVarChar; nomeno” appena nato e in crescita, da tene-
par.Size = 2; re sotto controllo. Potrebbe segnare la svol-
par.Value = “FI”; ta nell’uso dei linguaggi e nella definizione
cmd.Parameters.Add(parId); delle architetture (che fine fa il DAL?) così
come potrebbe essere abbandonato o modi-
List<Cliente> listaClienti = new List<Cliente>; ficato pesantemente come sintassi. Dipende
conn.open(); molto anche dai feedback che tutti noi dare-
using (SqlDataReader dr = cmd.ExecuteReader(Command mo a Microsoft.
Behavior.CloseConnection)) È bene tenere presente che se le performan-
{ ce sono l’elemento critico di un progetto, l’ap-
int nomeOrdinal = dr.GetOrdinal(“Nome”); proccio tradizionale, soprattutto per quanto
int cognomeOrdinal = dr.GetOrdinal(“Cognome”); riguarda l’accesso a basi dati SQL Server, re-
sterà la strada migliore.

N. 65 - Settembre/Ottobre 2005 VBJ 15


SPECIALE

Sicuramente è prematuro usarlo in un qual- si nel sistema operativo. Questa mossa toglie
siasi scenario che non sia solo sperimentale; di mezzo una percentuale enorme dei moti-
dare però un’occhiata e mandare dei feedback vi per cui a volte si vedono “schermi blu” (la
a Redmond è il modo migliore per ottenere stragrande maggioranza sono infatti dovuti ai
fra due o tre anni un prodotto più vicino alle driver delle schede video). Scheduler: è sta-
reali esigenze. ta introdotta una modalità chiamata “Multi-
media Class Scheduler Service” che dovreb-
Windows Longhorn Server be mantenere costanti i tempi di risposta nei
e Windows Vista processi che gestiscono elementi multimedia-
La nuova versione di Windows (Windows li. Scheduled File I/O: si tratta di un sistema
Vista e Longhorn Server) porta molte novità per dare priorità alle richieste di I/O. Questo
dal punto di vista dei servizi, dell’interfaccia tipo di funzionalità era atteso da tanti anni,
utente e delle numerose nuove funzionalità, adesso bisogna capire meglio come è imple-
tanto che saranno scritti molti libri per trat- mentato. Se funziona come deve, il risulta-
tarle. In questo articolo ci vogliamo occupare to netto è una percezione per l’utente di mi-
degli aspetti che hanno un impatto sugli svi- gliore e più rapida risposta alle proprie azio-
luppatori, ma che magari sono anche meno ni, perché attività di I/O secondarie vengono
note perché meno “coreografiche”. accodate, al contrario di quanto avviene oggi
Ci sono molti cambiamenti nel kernel e ai dove le richieste di I/O finiscono nella stessa
servizi di base di Windows. Da questo punto coda, indipendentemente dal fatto che proven-
di vista ci saranno alcune delle più rilevan- gano da un processo più o meno prioritario.
ti novità da quando è nato Windows NT. L’in- Protezione da malware/rootkit: ci sono tecni-
tento è quello di aumentare la sicurezza, la che per controllare il codice che gira in mo-
robustezza e le prestazioni percepite (tempi dalità kernel e per i processi critici che girano
di risposta alle azioni dell’utente) del sistema in modalità utente, tra l’altro usando un con-
operativo. La caratteristica secondo noi più trollo per verificare che il codice sia firmato
interessante è quella dello scheduled I/O, im- digitalmente. Bisognerà vedere quanto que-
portante anche per tutti coloro che scrivono sto sia realmente a prova di rootkit, ma per
software che deve avere prestazioni soft real- lo meno si dovrebbe ridurre un po’ (anche se
time, per esempio chi gestisce un protocollo non del tutto) la superficie di attacco. Servi-
di comunicazione su seriale che richiede un zi Windows: tante, tante novità.
controllo sui tempi di latenza. Vediamo pun- Le più visibili sono il delayed auto-start (il
to per punto le novità più significative. User servizio parte con un processo a priorità più
Mode Driver Framework: alcuni driver si pos- bassa di CPU e di I/O, così da non rallentare
sono eseguire in modalità User, pur avendo lo un’eventuale operatività dell’utente) e il re-
stesso modello di sviluppo; questo garantisce covery automatico anche in casi diversi dal
che un driver così caricato non possa danneg- crash (per esempio memory leak e resource
giare l’intero sistema. Molti driver non richie- leak). Le altre novità interessano la security,
dono di andare realmente in modalità Kernel con l’isolamento della sessione in cui girano
(è indispensabile solo per agganciare inter- i servizi dalle sessioni interattive e l’harde-
rupt e accedere direttamente all’I/O). Ciò au- ning dei token e dei privilegi (questo punto
menta la robustezza del sistema operativo. Ri- meriterebbe un intero articolo).
spondendo a una domanda è stato detto che i Registry: oltre alla funzionalità transaziona-
driver video in Windows Vista girano in mo- le (disponibile anche per il file system NTFS)
dalità utente; evidentemente una parte della c’è la virtualizzazione, che consente di ese-
comunicazione con la scheda video è gestita guire con utenti non-admin anche quelle ap-
da driver a più basso livello che girano in mo- plicazioni che cercano di scrivere sul Regi-
dalità kernel e che probabilmente sono inclu- stry dove non dovrebbero: tali modifiche al

16 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

Registry sono visibili solo all’applicazione e è spostare nella piattaforma la conoscenza dei
all’utente che le ha fatte, è come se ci fosse vari attributi “dei file”, che oggi è demandata
un registro virtuale per ogni applicazione e alle singole applicazioni. È possibile mettere in
ogni utente. Sembra una questione banale, relazione un dato o un file con un altro. WinFS
ma ci sono un’enormità di effetti collaterali fornisce il supporto per la memorizzazione del-
e di situazioni particolari da considerare (per le informazioni comuni a più applicazioni come
esempio, un antivirus deve intercettare tutte Contatti, Aziende, Persone: questo consente alle
le chiamate come se fossero reali) che richie- applicazioni e agli utenti di eseguire ricerche
dono un lavoro piuttosto complesso dal pun- mirate sugli item memorizzati, di evitare di me-
to di vista implementativo. morizzare gli stessi dati in location diverse e di
Questo ha un impatto diretto sui program- utilizzare attributi diversi per la stessa tipolo-
mi che devono filtrare le chiamate al registry gia di informazione. L’organizzazione delle in-
(gli antivirus, appunto) che dovranno adattar- formazioni si basa su schemi.
si a una nuova architettura per funzionare al Ogni schema descrive entità come eventi, per-
meglio. WoW64: Windows on Windows 64 bit sone, documenti, immagini e messaggi, defi-
consente di eseguire processi a 32 bit. Non è nendo gli attributi di ognuna di esse.
una vera novità perché è presente anche sulle Per esempio una Persona può avere più in-
versioni a 64bit di Windows 2003 e Windows dirizzi di posta elettronica, mentre un’Azienda
XP già esistenti. può contenere diverse entità di tipo persona.
I driver a 32 bit non sono supportati, un’ap- Questi schemi sono estendibili: è possibile de-
plicazione a 32 bit viene caricata in un “am- finirne di propri per le proprie informazioni.
biente virtuale” a 32 bit dove non si possono WinFS consente un’organizzazione gerarchica
richiamare altre DLL a 64 bit. Lo spazio di in- delle informazioni e una organizzazione rela-
dirizzamento è 2Gb o 4Gb (per le applicazioni zionale: per questo spesso si legge “Relational
che supportano i 3Gb, è un attributo del Por- File System”.
table Executable). C’è un impatto sul Registry, Vista la sua struttura è possibile ricercare dati
nel senso che le applicazioni a 32 bit vedono utilizzando query relazionali tramite il modello
una vista del Registry che consente di isola- a oggetti esposto direttamente, ma anche uti-
re le applicazioni a 32 bit da quelle a 64 bit. lizzando ADO.NET e SQL. Se uno più uno fa
L’interoperabilità tra 32 e 64 bit può avvenire sempre due, avrete già capito che si potrà in-
tramite COM, ma solo con componenti out-of- terrogare WinFS anche tramite LINQ. Ecco un
process e non con componenti in-process. esempio semplice:

WinFS Linq e WinFS


La sessione su WinFS è stata replicata per con- Table<Customers> clienti = db.Customers
sentirne la visione a tutti coloro che erano ri- using System.Storage;
masti fuori dalla sala strapiena; ciò testimonia using System.Data.Objects;
l’interesse verso questa tecnologia annunciata using Druker.Sales;
a PDC 2003, disponibile nella prima “Alpha” di
Longhorn (adesso Windows Vista) e poi separa- SalesData sd = new SalesData(salesConfig);
ta da quest’ultimo nell’agosto 2004.
Dall’agosto 2005 è disponibile una prima Beta foreach (Customer customer in sd.Customers where
di WinFS (installabile su XP SP2), non sarà in- LastName=’Brunetti’) Console.WriteLine(customer.FirstName);
cluso nella prima release di Windows Vista, ma
sarà reso disponibile come componente aggiun- // Aggiunta di un cliente
tivo. Rispetto ai file system tradizionali consen- Customer cliente = new Customer(id, Nome, Cognome);
te di categorizzare le informazioni memorizzate sd.Customers.Add(cliente);
tramite attributi definiti in uno schema. L’idea sd.SaveChanges();

N. 65 - Settembre/Ottobre 2005 VBJ 17


SPECIALE

Lo store WinFS è transazionale, consentendo Expression Interactive Designer


l’esecuzione di operazioni utilizzando i classi- Durante la plenaria e con un paio di sessioni de-
ci metodi BeginTransaction, CommitTransac- dicate sono stati presentati i nuovi prodotti del-
tion e AbortTransaction. la famiglia Expression Web Developer. L’obietti-
vo è fare un salto in avanti nella presentazione
ATLAS dei dati all’utente: il tema ricorrente degli ultimi
ATLAS è un’estensione del motore di anni (ma lo sarà anche per i prossimi) è “Enrich
ASP.NET per supportare il tanto discusso AJAX User Experience”. La famiglia dei prodotti com-
(Asyncronous Javascript And XML). Utilizzan- prende Quartz Web Designer, Acrylic e Sparkle.
do oggetti server, simili ai Web Control, è in Quartz Web Designer è il nuovo strumento per
grado di produrre interfacce web che eseguo- disegnare interfacce utente web che dovrebbe
no richieste a servizi esposti, senza eseguire i finalmente rendere più semplice la difficile in-
classici POST http. In pratica questi controlli terazione fra sviluppatori web, grafici, sviluppa-
inviano al client la “Client Script Library”, ba- tori server-side e IT manager. Come prima cosa
sata appunto su Javascript, che fornisce una Quartz genera codice molto pulito e aderente a
serie di servizi per invocare tramite XMLHt- XTHML 1.0 sia Transitional che Strict, può uti-
tp la parte server. lizzare le diverse tecniche di posizionamento dei
Le richieste di informazioni passano da un tag (dalle classiche tabelle a CSS-P) per lavora-
Service Bridge (che insieme alla script library re con vari browser. Con diversi “simulatori di
è incluso nel file AtlasCore.js) lato client, che browser” è in grado di effettuare una preview
a sua volta invoca i servizi server side. I servi- del risultato molto più aderente alla realtà: è
zi server-side possono essere i classici ASMX possibile anche effettuare prove di binding con
oppure servizi WCF (Indigo). dati reali presenti in una sorgente dati qualun-
Grazie all’integrazione con ASP.NET 2.0, pro- que per testare il risultato senza dover portare
xy e librerie lato client vengono generati in au- le pagine su un server web. Code snippet e In-
tomatico e sfruttano nativamente i moduli di tellisense aiutano nella scrittura del codice di
autenticazione, autorizzazione e caching clas- markup e di binding. Acrylic è invece uno stru-
sici di ASP.NET 2.0. I Web Service in un’appli- mento grafico per creare immagini e animazioni
cazione ATLAS producono il codice javascript vettoriali o classiche; l’alternativa a PhotoShop
lato client in base ai metodi esposti dal web per capirci. Acrylic è il secondo nato della fami-
service stesso. glia, e anche l’unico attualmente in Beta e sca-
Allo sviluppatore dell’interfaccia utente non ricabile gratuitamente da www.microsoft.com/
resta che scrivere le righe di codice Javascript expression. Si tratta di un tool espressamente
che invocano i metodi esposti per far scatena- dedicato ai grafici. Affronta in modo “ibrido” la
re la richiesta in background e utilizzare i dati definizione di layer, ibrido perché permette di
per modificare l’interfaccia utente; molti con- lavorare sia con vector-layer che con pixel-layer
trolli presenti in ATLAS (si utilizzano come i per consentire in qualsiasi momento di trasfor-
normali controlli asp: <atlas:TextBox>) ese- mare un layer da un tipo all’altro. Tra le featu-
guono già queste operazioni in automatico. re di rilievo segnaliamo elevate performance nel
Sono presenti anche numerosi controlli che pixel painting, modifica delle dimensioni (size
effettuano binding su tabelle HTML eseguen- e dpi) di un documento, brushes, strokes gra-
do dietro le quinte le operazioni più comuni di dient, pattern classici da strumento per dise-
inserimento, modifica e cancellazione. Anche gnatori e la capacità di modificare il canale al-
i Validation Control possono sfruttare questa pha di un layer nella clipboard, utile per creare
tecnologia per eseguire validazioni sui dati nel sfondi semitrasparenti da incollare in presenta-
database senza eseguire POST. È disponibile zioni Powerpoint o altri documenti.
uno starter kit [4] e nel 2006 dovremmo avere La caratteristica di maggior interesse per gli
presto una prima beta “GoLive”. sviluppatori è senz’altro la funzione di esporta-

18 VBJ N. 65 - Settembre/Ottobre 2005


SPECIALE

zione del layout finale in linguaggio XAML, so- solito codice? Su Internet [5] si può avere una
lida base della piattaforma Windows Presenta- preview online delle funzionalità di questa fa-
tion Foundation. Sarà così possibile integrare i miglia di prodotti.
grafici nel totale processo produttivo di un’appli-
cazione Windows e non solo, come adesso, nella System.Transaction 2.0
prima fase creativa del progetto. Sparkle, rea- La versione 2.0 di .NET ha fatto un passo avan-
lizzato completamente con Windows Presenta- ti nella gestione delle transazioni: non occorro-
tion Foundation, è il tool fondamentale per de- no più componenti basati su Enterprise Servi-
finire in modo visuale le interfacce utente del- ces (e quindi COM+) e si è semplificata (e al-
la prossima generazione. leggerita dal punto di vista dell’esecuzione) la
Le caratteristiche più interessanti sono l’im- gestione da codice. Quindi? Dalla Beta2 di Win-
portazione e la combinazione di elementi vet- dows Vista e ovviamente in Longhorn Server
toriali e bitmap, pieno supporto ai modelli 3D sia il file system NTFS che il Registry saran-
(geometry, materials, texture, camera, trasfor- no transazionali!
mazioni XYZ ecc) realizzabili da zero o impor- Questo rende più semplice la scrittura di ap-
tabili da famosi tool di terze parti. plicazioni che gestiscono immagini: viene in
Sarà facile definire animazioni 2D o 3D, grazie mente un sito web con immagini memorizza-
a comode form per realizzare timeline in modo te sul file system e dati associati memorizzati
intuitivo e alle funzioni rec-move-play dello stru- in un database.
mento. Piena integrazione con le funzionalità le- È possibile abbracciare sotto un’unica transa-
gate a video, è infatti possibile “applicare” un vi- zione la scrittura dell’immagine e dei dati nel
deo, come se fosse una texture 2D, a qualunque DB. Le transazioni possono abbracciare SQL
oggetto. Le avanzate caratteristiche tipografiche 2005 nativamente, MSMQ e SQL 2000 trami-
di Windows Presentation Foundation sono pie- te l’utilizzo trasperente del buon vecchio Mi-
namente supportate dal tool. Sparkle è un’appli- crosoft DTC.
cazione dedicata ai designer professionisti, ma
semplifica anche la vita agli sviluppatori .NET Conclusioni
con comode toolbox per inserire controlli “tra- È stata una PDC interessante e densa di no-
dizionali” (Canvas, DatePicker, Button, Textbox vità e informazioni utili. Ora ci aspettano cir-
ecc.), creare controlli compositi unendo diversi ca 2 anni di consolidamento delle conoscenze
oggetti semplici, applicare “trigger” per modi- attuali, relativamente a .NET 1.x e .NET 2.0
ficare l’aspetto dei controlli in modo condizio- durante i quali vedranno la luce WinFX, Win-
nale o definire sintassi di binding a design time dows Vista, Longhorn Server, Sharepoint 3.0,
con tanto di preview. C# 3.0 e forse Linq.
Il tool permette di definire sia l’aspetto del- In un certo senso possiamo affermare di aver
l’applicazione sia il suo comportamento, con- dato uno sguardo attraverso una finestra che
sentendo l’editing dei file di code-behind C# ci ha permesso di sapere come saranno i pros-
o VB.NET; tali file ovviamente possono essere simi 2 o 3 anni.
condivisi con Visual Studio 2005 per la gestione Ne è valsa decisamente la pena per non far-
completa di un’applicazione enterprise. Signifi- si trovare impreparati!
cative le funzionalità legate al deployment per
distribuire sia applicazioni stand-alone che ex- Riferimenti
press application, ovvero applicazioni “ospitate” [1] http://www.windowsworkflow.com/
da Internet Explorer. Nascerà quindi un nuova [2] http://msdn.microsoft.com/winfx/
categoria professionale di sviluppatori dell’in- [3] http://www.microsoft.com/windows/
terfaccia utente. [4] http://atlas.asp.net
Chi saranno i pionieri di questa nuova occupa- [5] http://www.microsoft.com/products/
zione: grafici evoluti o sviluppatori stanchi del expression/en/default.aspx

N. 65 - Settembre/Ottobre 2005 VBJ 19


MULTIMEDIA

Controlli multimediali
in Visual Basic 6
Non capita spesso di realizzare software dai contenuti multime-
diali. Questo articolo illustra le modalità di gestione di elementi
multimediali in VB6: non sarà forse molto originale, ma di sicuro
se ne potrà apprezzare la valenza evocativa per coloro che già
sanno ed educativa per coloro che ancora non sanno.

di Fabio Fabozzi

I
l supporto base che VB6 offre, soprattutto al L’applicativo sarà altresì com-
programmatore neofita, per riprodurre un file pletato da funzioni di apertu-
multimediale è il controllo ActiveX MS Multi- ra e chisura del file. La libreria
media Control. Tutti i programmatori VB si sono “winmm” consente di riprodur-
imbattuti in questo controllo e ne hanno potuto re e registrare file audio, midi,
apprezzare la semplicità d’utilizzo. Tuttavia esso e CD musicali. Il Form del Pro-
non è sufficiente per ogni tipo di applicazione. getto si presenta come in Figu-
Si vuole allora esaminare la libreria “winmm”, che ra 1. Per cominciare occorre di-
può risultare utile nell’ambito di applicazioni dai chiarare le variabili e le funzio-
contenuti multimediali più sofisticati. ni che entrano in gioco nell’ap-
L’articolo è rivolto, soprattutto, ai neofiti dello plicativo (Listato 1) dove:
sviluppo software in VB6.
• nome_file: è il nome del file
Eseguire file AVI con VB6 che dovrà essere aperto e ri-
In questo caso, l’applicativo di esempio riguar- prodotto;
derà la realizzazione di un lettore di file .avi, che • comando: è il tipo di coman-
consente di effettuare le seguenti operazioni: do che si vuole eseguire sul
file .avi;
• Esecuzione in Finestra • valore_ritorno: è il valore
• Esecuzione FullScreen che la funzione “mciSend-
• Stop/Pausa String()”, restituisce all’uten-
te a seconda dell’operazione
Fabio Fabozzi è progettista/sviluppatore software presso la da effettuare.
S4BT s.rl. di Latina, azienda che produce software in ambito
farmaceutico. È autore del libro”Intelligenza Artificiale con Anzitutto è necessario caricare
Visual Basic”, edito dal Gruppo Infomedia e collabora con
le riviste del gruppo come articolista. Tra i suoi principali
un file .AVI. Il controllo Com-
interessi: scienze cognitive, software per la disabilità, in- mon Dialog permette l’impo-
telligenza artificiale, crittografia, studio dei sistemi caotici, stazione dei filtri della tipolo-
applicazioni per calcolatori palmari. Studia Psicologia dei
gia del file e la procedura di
Processi Cognitivi presso la Facoltà di Psicologia1 dell’Uni-
versità “La Sapienza” di Roma. Può essere contattato via apertura (Listato 2). Si noti
e-mail all’indirizzo fabozzi@infomedia.it che nella procedura di apertu-

20 VBJ N. 65 - Settembre/Ottobre 2005


MULTIMEDIA

ra del file, il nome va tratta- trà rendere conto di quan-


to in questo modo: to poco tempo e con quan-
te poche righe di codice è
nome_file = Chr$(34) + nome_file + possibile scrivere un’appli-
Chr$(34) cazione multimediale (Li-
stato 3). Prendiamo ora in
Se si omette Chr$(34) – ossia considerazione il comando
gli apici – il file verrà aperto “Play video”. Tale coman-
ma non letto. Si noti la sintas- do, oltre ad eseguire un
si del comando “Open”: file video desiderato, lo
colloca in finestra “tiled”,
comando = “open “ + nome_file + “ cioè adatta alle dimensio-
alias video” ni proprie di quel file AVI.
L’effetto, che molti di voi
Si può notare, nell’ultimo avranno visto, è quello vi-
spezzone della riga di coman- sibile in Figura 2.
do, la dicitura “ alias video”. In Figura 1 Applicativo prjAVI Tuttavia, però, potrebbe
questo caso, il sistema, darà ad essere desiderabile aprire
un file .AVI di un certo nome, un file AVI direttamente
il nome generico di “video”, su all’interno di un control-
cui verranno svolte tutte le operazioni a segui- lo PictureBox e, quindi, adattare le dimen-
re. Tale nome, è comunque definibile dall’uten- sioni del file alle dimensioni del controllo
te: se avessi messo “alias cipolla”, avrei mani- stesso. Ciò consente di creare un applicativo/
polato un file video con l’alias di “cipolla”. Per visualizzatore, discreto e sofisticato. La pro-
eseguire un comando, sia esso un’esecuzione cedura che andiamo ad esaminare consente
FullScreen, normale o lo stop, viene utilizza- anche di poter creare un logo roteante per un
ta la seguente sintassi: applicativo. Tale logo, appunto, potrebbe es-
sere proprio un file AVI, di modeste dimen-
comando = “<denominazione del comando> video” sioni, che viene mandato in playback con ri-
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) petizione. Partiamo proprio da questo pun-
to, cioè, dalla ripetizione di un file AVI e dal-
Questa sintassi è la stessa che già abbiamo la sua implementazione. Ripetere un file AVI
visto per l’apertura del file e, come si può no- all’infinito è una cosa molto semplice, basta
tare, è molto simile per gli altri comandi che aggiungere la parola “repeat” al comando e il
vengono lanciati. Voglio riportare tutti i co- gioco è fatto:
mandi che fanno parte di questo applicativo
di esempio. In questo modo, il lettore si po- comando = “Play video” + “ repeat”

Listato 1 Variabili dell’applicativo

Option Explicit

Private Declare Function mciSendString Lib “winmm.dll” Alias “mciSendStringA” (ByVal lpstrCommand As String,ByVal lpstr-
ReturnString As String, ByVal uReturnLength As Long, ByVal hWndCallback As Long) As Long
Private nome_file As String
Private valore_ritorno As Long
Private comando As String

N. 65 - Settembre/Ottobre 2005 VBJ 21


MULTIMEDIA

Listato 2 Procedura di apertura del file .AVI Const WS_CHILD = &H40000000


Private Height As Long
Private Width As Long

Private Sub Command2_Click()


cd.Filter = “(*.avi)|*.avi” A questo punto, è possibile defini-
cd.FilterIndex = 0
re la procedura di apertura del file,
cd.FileName = “”
cd.ShowOpen che sarà quella riportata nel Listato
nome_file = cd.FileName 4. Dopo la fase di apertura, si passa
nome_file = Chr$(34) + nome_file + Chr$(34)
comando = “open “ + nome_file + “ alias video” alla fase di ridimensionamento del
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) filmato AVI e del “filling” del con-
End Sub
trollo PictureBox (Listato 5). Una
volta completate queste due proce-
Ricordatevi di rispettare lo spazio che inter- dure, si può riprodurre il file in questo modo:
corre tra l’apice e l’inizio della parola “repeat”.
Ora, la cosa più impegnativa sarà scrivere del comando=”Play AVIFile”
codice che vada ad adattare un filmato AVI al-
l’interno di una PictureBox. Consiglio di dise- Riproducendo un file AVI in una Picture-
gnare il controllo PictureBox in un nuovo Form, Box e con ripetizione (si ricordi l’aggiunta
perché la procedura di apertura del file è legger- del comando repeat), è possibile adornare
mente diversa da quella usata fino ad ora. Pri- l’applicazione di un eventuale cliente con
ma di tutto copiate nelle dichiarazioni del nuo- un logo animato creato “ad hoc”. Con que-
vo Form le variabili e le funzioni precedenti ed sto si conclude la panoramica sulla riprodu-
aggiungete queste nuove variabili: zione dei file AVI.

Eseguire file WAV


con VB6
Il controllo dei file
WAV, nel contesto
della creazione di ap-
plicazioni, è molto più
importante della ripro-
duzione di file AVI. Il
perché, della mia pre-
cedente affermazione,
è molto semplice. È co-
mune pensare che ap-
plicativi che presenti-
no al loro interno ri-
produzione di filma-
ti o di suoni, possa-
no essere in genera-
le programmi ludici.
Come abbiamo visto,
per la riproduzione
dei file AVI è possibi-
Figura 2 Riproduzione del file in “tiled window”
le adornare l’applicati-
vo creato per un clien-
te. Per ciò che concer-

22 VBJ N. 65 - Settembre/Ottobre 2005


MULTIMEDIA

ne i suoni, la loro importanza è di Listato 3 Funzioni di manipolazione di un file AVI


gran lunga maggiore. Si pensi, ad
esempio, a tutte quelle applicazio-
ni critiche, in cui chi utilizza un sof- Private Sub Play()
tware ha bisogno di segnali, di allar- comando = “play video”
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
mi, di avvisi. In questi contesti, po-
End Sub
ter riprodurre un suono è una com-
ponente essenziale. Al di là di tutte Private Sub Play_FullScr()
comando = “play video fullscreen”
queste implicazioni, passiamo alla valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
riproduzione e all’esecuzione, più in End Sub
generale, dei suoni o dei file WAV. Private Sub Chiudi()
La finestra del progetto di esempio comando = “close video”
per i file WAV, sarà molto simile a valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
End Sub
quella dei file AVI. Nel progetto al-
legato, è possibile vedere – nella se- Private Sub Stop()
comando = “stop video”
zione delle dichiarazioni – che que- valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
ste corrispondono a quelle presenti End Sub
nel progetto di esempio per gli AVI.
Le funzioni che si andranno ad im-
plementare sono le seguenti: liarità può essere rappresentata dalla funzione
di “Riavvolgimento di un file WAV”:
• Apertura di un file WAV
• Esecuzione di un file WAV comando = “seek sound to start”
• Riavvolgimento di un file WAV valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
• Stop/Pausa di un file WAV
• Chiusura di un file WAV Ho chiamato questa funzione “riavvolgimen-
to”, che evoca la vecchia funzione presenti sui
L’apertura del file WAV è del tutto simile riproduttori a cassetta di una volta. Infatti tale
a quella di un file AVI, ma cambia qualcosa funzione riporta il file all’inizio. L’elenco com-
nella stringa di comando: pleto delle funzioni di base è visibile nel Lista-
to 6. Una funzione particolare può essere quella
comando = “open “ + nome_file + “ type waveaudio alias sound” di dare la possibilità all’utente di registrare un
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) file audio. Le modifiche da fare, a tale propo-
sito, sono poche. Basta aggiungere due Com-
Ciò significa che l’alias del file waveaudio su mandButton sul form del progetto che porti-
cui verranno effettuate le operazioni avrà l’alias no ad esempio queste due etichette:
“sound”. Le funzioni che manipolano i file WAV
non sono né complesse né, tantomeno, dissimi- • Registra WAV
li da quelle già viste per i file AVI. Una pecu- • Salva file registrato

Listato 4 Apertura file AVI per la PictureBox

Private Sub Apri_File_PB( )


comando = = “open “ + nome_file + “ type AVIVideo alias AVIFile parent “ + CStr(PictureBox.hWnd) + “ style “ +
Cstr(WS_cHILD)
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
End Sub

N. 65 - Settembre/Ottobre 2005 VBJ 23


MULTIMEDIA

Si evince che la registrazio- Listato 5 Ridimensionamento del file AVI nella PictureBox
ne è suddivisa almeno in due
fasi; in realtà il processo è leg-
germente più lungo ma non Private Sub Ridimensiona_In_PB( )
complicato. Se è stato carica- Height = PictureBox.ScaleHeight/Screen.TwipsPerPixelY
Width = PictureBox.ScaleWidth/Screen.TwipsPerPixelX
to precedentemente un suo-
comando = = “Put AVIFile window at 0 0 “ + Cstr(Width) + “ “ + CStr(Height)
no, lo si chiude e se ne crea valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
uno vuoto disponibile per la End Sub

registrazione:
Si registra il suono desiderato per quanto
comando = “close sound” si vuole.
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) Quando si vuole interrompere la registrazio-
comando=”open new type waveaudio alias suono” ne, si utilizza la funzione di “Stop” presente
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) nel Listato 6. Per salvare il suono si utilizza
questo semplice comando:
Il passo successivo consiste nella registra-
zione vera e propria del suono, che è molto comando = “save sound” + nome_suono
semplice: valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

comando = “record sound” dove nome_suono è una variabile di tipo


valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) String, in cui è stato immesso un nome da
inputbox o da textbox, una fun-
zionalità semplice da implemen-
Listato 6 Funzioni di manipolazione di un file WAV
tare nell’applicativo.
Questo conclude la panoramica
relativa alla manipolazione dei
Private Sub Esegui_WAV()
comando = “play sound” file WAV.
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
End Sub
Conclusioni
Private Sub Apri_WAV() Abbiamo visto solo alcune delle
cd.Filter = “(*.wav)|*.wav” funzionalità principali della libre-
cd.FilterIndex = 0
cd.FileName = “” ria “winmm”.
cd.ShowOpen A tale proposito, credo che quel-
nome_file = cd.FileName
nome_file = Chr$(34) + nome_file + Chr$(34) le relative alla manipolazione di
comando = “open “ + nome_file + “ type waveaudio alias sound” suoni siano importanti per avere
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)
informazioni e allarmi da un pro-
End Sub
cesso software.
Private Sub Riavvolgi_WAV() Consiglio caldamente di consul-
comando = “seek sound to start”
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) tare la bibliografia alla fine di que-
End Sub sto articolo, dove potete trovare al-
Private Sub Chiudi_WAV()
tre funzione relative alla riprodu-
comando = “close sound” zione dei CD o dei file MIDI, che
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) possono sempre risultare utili.
End Sub

Private Sub Stop_WAV() Bibliografia


comando = “stop sound”
valore_ritorno = mciSendString(comando, vbNullString, 1024, 0) [1] Francesco Balena – I trucchi di
End Sub Visual Basic 6, Mondadori Infor-
matica, 2003, ISBN 8883314778

24 VBJ N. 65 - Settembre/Ottobre 2005


APPLICAZIONI

Controllo Remoto
in Visual Basic .NET
Seconda puntata

di Stefano Corti

I
n questa seconda parte dedicata al nostro pro- spondere al Controller (client)
getto di controllo remoto in Visual Basic .NET, per mezzo di un appropriato co-
spiegheremo in dettaglio il codice di implemen- mando in formato stringa (RE-
tazione della classe RemoteStructure. PLYDRIVESSEQUENCE>).
Abbiamo detto che questa classe è estremamente A questo punto dobbiamo com-
importante, in quanto costituisce la classe base dal- pletare la stringa di risposta con
la quale altre classi erediteranno alcune proprietà e tutte le lettere di unità individua-
metodi fondamentali. Incominciamo subito a dare te. Utilizziamo un ciclo For Each
uno sguardo alle linee di codice di un primo sem- Next per iterare automaticamen-
plice metodo pubblico. te l’array privato di tipo string
oUnits e collochiamo sequen-
Public Function getLogicalUnits() As String zialmente tutti i valori all’inter-
oSequenzaDrives = “REPLYDRIVESSEQUENCE>” no della nostra stringa, ciascuno
oUnits = Environment.GetLogicalDrives() separato da un apposito caratte-
For Each oDrive In oUnits re separatore. In questo specifico
oSequenzaDrives &= oDrive & “*” caso utilizziamo il carattere aste-
Next risco. A questo punto nel blocco
Return oSequenzaDrives Select principale del server dob-
End Function biamo collocare il codice neces-
sario per intercettare ed eseguire
Questo metodo, che chiamiamo getLogicalUnits, questa specifica operazione.
consente di ottenere un array di tipo string conte-
nente le radici di tutte le unità logiche presenti nel Case Is = “GETDRIVESLIST”
sistema della macchina controllata, quindi eventua- writer.Write(objStruct.getLogicalUnits())
li dischi fisici e partizioni logiche. Per ottenere tutto sentText.Clear()
questo è sufficiente invocare il metodo GetLogical- sentText.Text = objStruct.getLogicalUnits()
Drives() della classe Environment. In questo caso,
come si può osservare, il Target (server) dovrà ri- I lettori più attenti certamen-
te avranno intuito che, in fase
di inizializzazione della Form1,
Stefano Corti si occupa di programmazione PHP e JSP abbiamo già provveduto a istan-
lato server, della piattaforma .NET e di integrazione di
sistemi legacy con le nuove realtà del web, soprattutto in
ziare un oggetto (objStruct) dal-
ambito gestionale, bancario e finanziario. È attualmente alle la classe RemoteStructure. Non
dipendenze di un primario gruppo bancario italiano. Può resta quindi che invocare il me-
essere contattato via email: scorti@infomedia.it. todo precedentemente illustrato

26 VBJ N. 65 - Settembre/Ottobre 2005


APPLICAZIONI

te nella stringa ven-


gono estratte e col-
locate in un nuovo
array di tipo string
a_splitResult. Pos-
siamo quindi itera-
re questo array e,
all’interno del ci-
clo medesimo, ri-
chiamare il metodo
Add() per posiziona-
re in ListView1 tutte
le informazioni ne-
cessarie. Un altro
importante metodo
della nostra classe
RemoteStructure è
certamente getFile-
sAndDirectories().
Figura 1 I controlli per la gestione dei file Si tratta di un me-
todo pubblico che
restituisce varie ti-
pologie di informa-
ed iniettare nel socket di flusso la stringa così zioni su file e directory residenti sulla macchi-
ottenuta. Vediamo ora ciò che avviene nel pro- na remota. Questo metodo utilizza il metodo
gramma Controller. privato getInformation(). Ci sembra opportuno
ricordare che getInformation() viene dichiara-
If job(0) = “REPLYDRIVESSEQUENCE” Then to Private dal momento che deve essere acces-
Dim a_delimStr As String = “*” sibile solo all’interno della classe nella quale
Dim a_delimiter As Char() = a_delimStr.ToCharArray() viene definito, poiché i valori restituiti ven-
Dim a_splitResult As String() = Nothing gono utilizzati esclusivamente da altri metodi
a_splitResult = job(1).Split(a_delimiter) implementati all’interno della classe medesi-
Dim a_inList As String ma. Al metodo GetInformation() viene passa-
ListView1.Items.Clear() to, per riferimento, il contenuto della variabile
For Each a_inList In a_splitResult stringa privata oFileDirName. Tale variabile,
ListView1.Items.Add(a_inList) come abbiamo visto, viene già inizializzata al-
Next l’interno del costruttore sovraccarico della no-
End If stra classe, ma anche all’interno del codice di
implementazione della proprietà Profile, come
Anche in questo caso abbiamo previsto una si può chiaramente evincere osservando la se-
serie di condizioni If End If per analizzare tutti guente porzione di codice
i comandi provenenti da Target, laddove ogni
comando è contenuto nell’array job con indi- Sub New()
ce 0 e i relativi parametri in indice 1. Tutte le Me.oFileDirName = “C:\”
unità logiche trasmesse (separate dall’apposito End Sub
carattere separatore) devono popolare un con- Sub New(ByVal FileName As String)
trollo ListView che chiamiamo ListView1. Tut- Me.oFileDirName = FileName
te le lettere di unità contenute sequenzialmen- End Sub

N. 65 - Settembre/Ottobre 2005 VBJ 27


APPLICAZIONI

Listato 1 Il metodo pubblico getFilesAndDirectories() della classe Remote si approfondita sulla tipo-
Structure logia del file, tentando an-
che di eseguire una lettu-
Public Function getFilesAndDirectories() As String ra, nel caso si tratti di un
If File.Exists(oFileDirName) Then file di testo (quindi non
oReturned = GetInformation(oFileDirName)
file binari), ed eseguendo
Try
oStream = New StreamReader(oFileDirName) un’esplorazione in profon-
oReturned &= oStream.ReadToEnd() dità nel caso che il percor-
Catch ec As IOException
oReturned &= “Errore di I/O su file: “ & ec.Message so il questione non sia un
Catch ec As ArgumentException file bensì una directory. Ve-
oReturned &= “Errore Intercettato: “ & ec.Message
End Try
diamo in dettaglio queste
ElseIf Directory.Exists(oFileDirName) Then funzionalità analizzando il
Dim i As Integer Listato 1.
Dim h As Integer
oReturned = GetInformation(oFileDirName) Prima di tutto dobbiamo
oDirectoryList = Directory.GetDirectories(oFileDirName) stabilire se il percorso con-
oDirectoryFileList = Directory.GetFiles(oFileDirName)
oReturned &= vbCrLf & _ tenuto nella variabile pri-
“Contenuto della Directory: “ & vbCrLf vata oFileDirName punta
For i = 0 To oDirectoryList.Length - 1
oReturned &= oDirectoryList(i) & vbCrLf
ad un file oppure a una di-
Next rectory. Possiamo nuova-
For h = 0 To oDirectoryFileList.Length - 1 mente utilizzare un meto-
oReturned &= oDirectoryFileList(h) & vbCrLf
Next do della classe File per ot-
Else tenere questo scopo. Rite-
oReturned &= “Errore: “ & oFileDirName & “ non trovato.” & vbCrLf
End If niamo opportuno ricordare
Return oReturned che la classe File della FCL
End Function
(Framework Class Library)
del .NET Framework espo-
ne esclusivamente membri
Public Property Profile() As String statici, quindi non è necessario istanziare oggetti
Get da questa classe, bensì è possibile invocare di-
Return oFileDirName rettamente il metodo che ci interessa, passan-
End Get do l’argomento al parametro del metodo stesso.
Set(ByVal Value As String) Utilizziamo, ad esempio, il metodo pubblico Exi-
oFileDirName = Value sts() passando come argomento della funzione
Set il percorso all’interno del file system, prestando
End Property particolare attenzione che il parametro specifi-
cato sia formalmente corretto, altrimenti verrà
In questo modo, la variabile privata oFileDir- generata un’eccezione che il nostro codice non
Name contiene sempre un percorso assoluto al- sarà in grado di intercettare e gestire adeguata-
l’interno del file system della macchina Target mente. Il metodo Exists() restituisce un valore
che punta direttamente ad un qualsiasi file o ad boolean, quindi otteniamo True nel caso il pa-
una qualsiasi directory. Il nostro metodo privato rametro passato punti ad un file realmente pre-
utilizza una serie di metodi esposti dalla classe sente sul computer, oppure False in caso con-
File appartenente al namespace System.IO per trario. Vediamo ora di applicare lo stesso me-
ricavare informazioni dettagliate su un particola- todo alla classe Directory che si comporta esat-
re file o su una specifica directory, come ad esem- tamente come la classe File, esponendo quindi
pio la data di creazione, di modifica e dell’ultimo una nutrita seria di metodi statici per il tratta-
accesso. Questi dati vengono restituiti dal meto- mento delle directory. Nel caso il percorso spe-
do getFilesAndDirectories() che esegue un’anali- cificato punti ad una directory – cosa che pos-

28 VBJ N. 65 - Settembre/Ottobre 2005


APPLICAZIONI

Listato 2 Gestione del comando GETREMOTESTRUCTURELIST all’interno mo che il metodo descrit-


della struttura Select Case EndSelect to restituisce valori pura-
mente testuali che verran-
Case Is = “GETREMOTESTRUCTURELIST” no visualizzati in un’appo-
If job(1) = “CONTENUTO DELLA DIRECTORY REMOTA” Then sita area di testo all’inter-
Try
no della GUI del Control-
Dim root As DirectoryInfo = Directory.GetParent(objStruct.Profile)
Dim abso As String = root.FullName ler. L’utente potrà quindi
objStruct.Profile = abso vedere le caratteristiche
writer.Write(objStruct.exploreRemoteDirOrFil())
sentText.Clear() di un particolare file e i
sentText.Text = objStruct.exploreRemoteDirOrFil() contenuti di una partico-
Catch nre As System.NullReferenceException
writer.Write(“ERRORMAINDIRECTORY>NOARGS”)
lare directory senza ave-
Catch nrg As Exception re la possibilità di esegui-
MessageBox.Show(“Eccezione Intercettata: “ & _ re alcuna esplorazione
nrg.Message, “Eccezione Sollevata”, _
MessageBoxButtons.OK, MessageBoxIcon.Error) gerarchica. L’interfaccia
End Try utente del Controller, il
Else
objStruct.Profile = job(1) cui progetto verrà tratta-
writer.Write(objStruct.exploreRemoteDirOrFil()) to approfonditamente in
sentText.Clear()
sentText.Text = objStruct.exploreRemoteDirOrFil()
seguito, prevede una se-
End If rie di schede selezionabili
mediante altrettanti Con-
trol Tabs. Una scheda par-
siamo sempre verificare con Exists() – inizializ- ticolarmente importante, alla quale facciamo su-
ziamo due variabili di tipo Integer i e h. Innanzi bito riferimento, è certamente quella contenen-
tutto invochiamo sempre il nostro metodo priva- te tutti i controlli per le funzioni di file mana-
to getInformation() per ottenere informazioni di ger (vedi Figura 1). Possiamo facilmente nota-
base sulla nostra directory, dopo di ché dobbiamo re che la zona superiore della scheda contiene i
analizzare la directory per verificare se vi sono controlli per l’esplorazione delle directory e dei
contenuti dei file eventualmente insieme ad al- file sul PC locale in uso, mentre nella parte sot-
tre directory. Chiamiamo quindi i metodi stati- tostante si possono trovare tutti i pulsanti che
ci GetDirectories() e GetFiles() che restituiscono consentono di eseguire le funzionalità di base
matrici private a una dimensione di tipo string di file management sulla macchina remota. Il
contenenti rispettivamente la
lista delle eventuali directory
Listato 3 Metodo pubblico per la rimozione di file e cartelle
e degli eventuali file contenu-
ti nella directory analizzata. A
questo punto non ci resta che
Public Function deleteDirOrFil(ByVal pathTODEL As String) As String
iterare questi due array di tipo Dim retS As String = Nothing
string per mezzo di due cicli If Directory.Exists(pathTODEL) Then
For Next utilizzando la pro- Directory.Delete(pathTODEL)
retS = “Directory “ & pathTODEL & “ eliminata.”
prietà Length (-1) per deter- End If
minare il numero totale degli If File.Exists(pathTODEL) Then
File.Delete(pathTODEL)
elementi presenti nell’array. retS = “File “ & pathTODEL & “ eliminato.”
Tutti i file e tutte le directory End If
If retS Is Nothing Or retS = “” Then
ricavate possono quindi esse- retS = “Attenzione: Il percorso “ & pathTODEL & “ non esiste.”
re copiati nella variabile pri- End If
vata oReturned che viene uti-
Return retS
lizzata per restituire il valore End Function
in uscita dal metodo. Precisia-

N. 65 - Settembre/Ottobre 2005 VBJ 29


APPLICAZIONI

Listato 4 Codice che gestisce la richiesta di conferma nella GUI del Controller in seguito al comando preposto
all’eliminazione di file o directory sulla macchina Target

Private Sub elimButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles elimButton.Click


Dim messGo As String = “DELETESELECTEDFILEDIRECTORY>”
Dim prFD As String
Dim promptResult As DialogResult
Dim list_x As ListView.SelectedListViewItemCollection
list_x = Me.ListView1.SelectedItems
Dim i_list_x As ListViewItem
For Each i_list_x In list_x
messGo &= i_list_x.Text.ToString()
prFD = i_list_x.Text.ToString()
Next
If (messGo = “DELETESELECTEDFILEDIRECTORY>”) Then
MessageBox.Show(“Dovete prima selezionare un file o una directory da eliminare.”, _
“Messaggio di Errore”, MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
promptResult = MessageBox.Show(“ATTENZIONE !!! “ & vbCrLf & “Siete sicuri di volere definitivamente eliminare” & _
vbCrLf & prFD & “ ?”, “Attenzione !!! Richiesta di Conferma”, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If promptResult = DialogResult.Yes Then
Try
writer.Write(messGo)
inMessages.Clear()
inMessages.Text &= vbCrLf & “Comando Inviato: “ & vbCrLf & _
messGo
Catch exception As SocketException
inMessages.Text &= “Errore di comunicazione con il computer remoto: “ & _
exception.Message & vbCrLf
Catch ex As Exception
inMessages.Text &= “Errore: “ & ex.Message & vbCrLf
End Try
End If
End If
End Sub

pulsante “Unità Logiche” ci consente di ottene- objStruct.Profile = job(1)


re la lista completa delle partizioni presenti su Try
Target, come abbiamo in precedenza visto. Un writer.Write(objStruct.exploreRemoteDirOrFil())
altro pulsante molto importante è certamente sentText.Clear()
“Esplora Elemento Selezionato”, che consente sentText.Text = objStruct.exploreRemoteDirOrFil()
di scendere di un livello nella scala gerarchica Catch
del file system remoto, popolando il ListView1 ...
con tutti i file e le cartelle presenti nel percor- End Try
so selezionato. La pressione di questo pulsan- End If
te scatena un evento il cui codice associato cat- In questa fase andiamo quindi ad implementa-
tura il percorso assoluto presente in Listview1 re il metodo exploreRemoteDirOrFil all’interno
e costruisce la stringa da trasmettere a Target, della nostra classe RemoteStructure, in quanto,
facendola precedere dal comando GETREMO- come possiamo vedere, dovrà essere invocato
TESTRUCTURELIST>. Tale comando, unita- per l’oggetto objStruct di tipo RemoteStructu-
mente al parametro trasmesso, viene interpre- re. Si noti che la proprietà Profile di objStruct
tato dal server mediante la consueta struttura viene impostata sulla base del valore stringa
Select Case End Select. contenuto in job(1). Tale stringa contiene il per-
corso assoluto del file o della directory da esa-
Case Is = “GETREMOTESTRUCTURELIST” minare selezionati nella GUI del Controller. In

30 VBJ N. 65 - Settembre/Ottobre 2005


APPLICAZIONI

questo modo la variabile stringa privata della ga oSequenzaDirFil concatenando il valore re-
nostra classe assumerà il valore di tale percor- stituito dalla proprietà Name dell’oggetto dr di
so. Implementiamo ora il metodo osservando tipo DirectoryInfo. In questo caso la proprietà
il Listato 2. Questa volta utilizziamo i metodi Name non restituisce il percorso completo ed
di istanza della classe DirectoryInfo. Creiamo assoluto delle eventuali sottodirectory contenu-
dunque un oggetto di tipo DirectoryInfo pas- te nella directory superiore di riferimento, ben-
sando come argomento del costruttore il valore sì solamente i nomi di tali cartelle. Noi abbiamo
corrente della variabile privata oFileDirName. invece bisogno di concatenare esclusivamente
Chiamiamo questo oggetto di. Se la directory percorsi completi. Tali percorsi devono inizia-
esiste e il percorso contenuto nella variabile re sempre con la radice dell’unità logica di ri-
oFileDirName non punta ad un file, possiamo ferimento, poiché è in questo modo che vengo-
iniziare a riempire la variabile privata oSequen- no visualizzati nel ListView1 del controller per
zaDirFil con l’apposito comando da restituire, potere essere facilmente ritrasmessi al Target
mediante il nostro socket di flusso, al program- sotto forma di concatenazioni di stringhe. Se la
ma Controller (REPLYREMOTEDIR>). Veri- nostra stringa oFileDirName non dovesse ter-
fichiamo quindi se all’interno della directory minare con il carattere backslash, è necessario
corrente vi sono altre directory, mediante la aggiungerlo, quindi concatenare il nome rela-
seguente linea di codice tivo della sottocartella individuata in ogni ciclo
dell’iterazione e infine terminare con il caratte-
Dim listadir As DirectoryInfo() = di.GetDirectories re separatore asterisco.

Otteniamo così un array di elementi che pos- Dim listadir As DirectoryInfo() = di.GetDirectories
sono essere manipolati ed iniettati sequenzial- Dim dr As DirectoryInfo
mente in una stringa mediante un carattere se- For Each dr In listadir
paratore, tecnica che abbiamo già analizzato in If oFileDirName.EndsWith(“\”) Then
precedenza. oSequenzaDirFil &= oFileDirName & dr.Name & “*”
All’interno di questo specifico ciclo For Each Else
Next è importante eseguire un controllo sulla oSequenzaDirFil &= oFileDirName & “\” & dr.Name & “*”
correttezza formale del percorso assoluto del End If
file system e assicurarsi che la formazione del- Next
le stringhe che contengono i percorsi completi
delle directory siano perfettamente ricostruiti, Per ottenere invece una lista completa dei
poiché, in caso contrario, esse verranno visua- file presenti all’interno della cartella selezio-
lizzate nel ListView1 all’interno della GUI del nata, utilizziamo nuovamente il metodo stati-
Controller e, qualora selezionati per un’eventua- co GetFiles() della classe Directory che ritor-
le successiva operazione, l’errore si ribaltereb- na una matrice facilmente attraversabile con
be nuovamente su Target, generando un erro- il consueto ciclo For Each Next. Dopo l’ese-
re logico, previsto tra l’altro nelle ultime righe cuzione completa dei due cicli di cui abbia-
di codice del Listato 2, nell’ultima condizione mo parlato, tutti i valori ricavati (in sequenza
Else, laddove il percorso fornito dal Controller tutte le directory, seguite da tutti i file presen-
non sia corrispondente ad uno specifico file o di- ti nella cartella di riferimento, come sappiamo
rectory esistenti all’interno del file system della contenuta nella variabile privata oFileDirName
macchina remota. All’interno del ciclo iteratore che viene istantaneamente modificata in base
verifichiamo con il metodo EndsWith se l’ulti- ai nuovi settaggi della proprietà profile) si trova-
mo carattere della variabile oFileDirName cor- no concatenati nella variabile stringa oSequen-
risponda al carattere ASCII backslash (“\”). Se zaDirFil, il cui valore viene direttamente resti-
il valore boolean ritornato dal metodo è True tuito dal nostro metodo. In ultima analisi, se il
proseguiamo la costruzione della nostra strin- percorso selezionato nel ListView1 punta ad un

N. 65 - Settembre/Ottobre 2005 VBJ 31


APPLICAZIONI

file, tale procedimento non avrebbe senso, ra- nostro metodo exploreRemoteDirOrFil(). L’ulti-
gione per cui ci limiteremo a ricavare le infor- mo metodo definito all’interno della classe Re-
mazioni di base del file stesso invocando il me- moteStructure serve per eliminare cartelle e file
todo privato getInformation, precedentemente sul PC remoto.
descritto. Come abbiamo visto, se anche questa Si tratta di un metodo molto semplice che uti-
condizione non viene soddisfatta, è facilmente lizza i metodi statici Delete() esposti dalle clas-
intuibile che il percorso del file system sia sta- si File e Directory e restituisce un messaggio
to trasmesso erroneamente o incompleto, caso stringa contenente l’esito positivo o negativo
previsto dall’ultima condizione Else. Riteniamo dell’operazione. Si veda il Listato 3 per l’imple-
oppurtuno sottolineare l’importanza del meto- mentazione del relativo codice. In questo con-
do appena definito, in quanto, unitamente alla testo, riteniamo opportuno soffermarci un poco
proprietà Profile, ci consente di svolgere mol- sul relativo codice scritto per il programma Con-
te operazioni di base su file e cartelle residenti troller. Nella scheda di File Manager possiamo
su Target. All’interno della struttura Select nel- trovare l’apposito pulsante la cui pressione sca-
la Form1 del server, abbiamo previsto anche al- tena l’evento richesto dalla nostra procedura.
cuni casi paricolari. Più precisamente vogliamo Prima di tutto dobbiamo essere sicuri che
gestire il caso in cui dal Controller venga gene- l’utente desideri effettivamente la cancellazio-
rato un comando che ci chieda di risalire di un ne del file o della cartella selezionati nel Li-
livello all’interno della struttura gerarchica di stView1. Non appena il relativo comando vie-
file e cartelle, senza modificare il codice di im- ne immesso nel socket di flusso e ricevuto dal
plementazione della nostra classe. server, questi provvederà immediatamente alla
cancellazione del file o della directory specifi-
Case Is = “UPONEREMOTELEVEL” cata nel parametro, senza alcuna possibilità di
Try recupero. Questa è la ragione per la quale rite-
Dim root As DirectoryInfo = Directory.GetParent(objStruct. niamo doveroso inserire una sorta di control-
Profile lo “lato client” prima di procedere con l’invio
Dim abso As String = root.FullName del comando.
objStruct.Profile = abso Utilizziamo per questo scopo una semplice fi-
writer.Write(objStruct.exploreRemoteDirOrFil()) nestra di dialogo che ci chiede se siamo sicuri di
sentText.Clear() volere cancellare definitivamente sulla macchi-
sentText.Text = objStruct.exploreRemoteDirOrFil() na remota il file o la directory specificata.
Catch nre As System.NullReferenceException In caso affermativo, l’esecuzione del program-
writer.Write(“ERRORMAINDIRECTORY>NOARGS”) ma prosegue con il consueto blocco Try Catch,
Catch nrj As Exception che gestisce il codice che scrive nel socket TCP/
MessageBox.Show(“Errore: “ & _ IP aperto la sequenza binaria corrispondente ai
nrj.Message, “Messaggio di Errore”, _ caratteri ASCII della stringa che costituisce il
MessageBoxButtons.OK, MessageBoxIcon.Error) comando impartito insieme al relativo parame-
End Try tro. Tale parametro, ovviamente, non sarà altro
che il percorso assoluto e completo della risorsa
Non dobbiamo fare altro che invocare il me- selezionata nel nostro controllo ListView1.
todo GetParent() della classe Directory passan-
do come argomento il valore (stringa) della pro- Conclusioni
prietà Profile dell’oggetto objStruct. Nella prossima puntata descriveremo un’al-
Per ottenere il percorso completo della di- tra importante classe del nostro progetto che
rectory così ottenuta utilizziamo la proprietà ci consente di controllare i processi in ese-
FullName della classe DirectoryInfo. Il valore cuzione, di creare nuove cartelle e di otte-
restituito viene utilizzato per impostare nuova- nere particolari informazioni sulla configu-
mente la proprietà Profile e quindi invocare il razione del PC remoto.

32 VBJ N. 65 - Settembre/Ottobre 2005


DATABASE

Supporto XML in
SQL Server 2005
Sql Server 2005 introduce il tipo di dato nativo XML per
trattare documenti e frammenti XML, insieme a metodi
specifici per interrogare e modificarne il contenuto. XQue-
ry è il linguaggio implementato per le interrogazione dei
dati XML attraverso i nuovi metodi di interrogazione.

di Francesco Quaratino

X
ML (eXtensible Markup Language) ha rap- tabase relazionali con supporto
presentato di fatto una rivoluzione nel con- XML (XED), basata sul motore
cetto di rappresentazione e di scambio dei di persistenza dei dati [1][2]: in
dati (vedi Riquadro 1). A suggerirne l’utilizzo negli un database NDX il documen-
ambiti più disparati dell’informatica sono le sue pre- to XML costituisce l’unità fon-
ziose capacità intrinseche, come quella di astrarre il damentale di persistenza, men-
contenuto di un documento dalla sua presentazione, tre in un XED la persistenza
essere autodescrittivo, semplificare la condivisione continua ad essere affidata ad
dei dati tra piattaforme indipendenti, essere leggi- un motore relazionale oppure
bile dall’uomo e usare una struttura gerarchica di object oriented.
archiviazione dei dati. In particolare, il fatto di es- Il consorzio XML:DB Iniziati-
sere un formato di dati auto-descrittivo implica la ve [3], che si occupa della defi-
possibilità di descrivere il medesimo dato con at- nizione di una API standard per
tributi diversi: in altre parole, un dato caratterizza- la gestione dei database XML,
to da attributi variabili, ciò che si intende per dato ha definito i seguenti requisiti
semi-strutturato (semi-structured data) o destrut- fondamentali per un database
turato. Poiché tale possibilità è sconosciuta al mo- nativo XML (NDX):
dello di dati relazionale, è proprio questo particola-
re aspetto dell’XML che mette in luce il vantaggio 1. deve presentare un modello
maggiore di avere un supporto XML o, ancor me- logico per la gestione dei do-
glio, un tipo di dato nativo XML in un database re- cumenti XML e fornire stru-
lazionale puro come Sql Server. A questo proposito, menti, conformi a tale model-
è bene tenere presente la distinzione fondamenta- lo, per memorizzare ed inter-
le che esiste tra database nativi XML (NDX) e da- rogare questi documenti. Il
database può implementare
un proprio modello oppure
Francesco Quaratino è consulente in ambito di proget- adottare uno di quelli dispo-
tazione e amministrazione di database OLTP e OLAP, oltre
che di applicazioni software orientati ai dati. È certificato
nibili come quelli utilizzati
MCDBA e sviluppa in VB6, ASP, VB.NET e ASP.NET. Può da XPath o XML Infoset;
essere contattatto attraverso il sito di divulgazione infor- 2. deve avere come unità fonda-
matica http://www.xplayn.org. mentale di memorizzazione il

N. 65 - Settembre/Ottobre 2005 VBJ 33


DATABASE

documento XML, allo stesso modo in cui CREATE TABLE xml_tab


la tabella è l’unità di base nei database re- (
lazionali; id INT PRIMARY KEY,
3. deve essere indipendente dal modello fi- xml_col XML
sico di storage. )
GO
In un’accezione più ampia, invece, possono es-
sere considerati database XML quei database Alla stregua di un campo tradizionale del
che, pur non offrendo un tipo di persistenza del modello relazionale, per il campo XML si
dato XML, espongono metodi di accesso tipici può specificare se ammette valore NULL o
della tecnologia XML (XPath, XQuery, DOM). meno, fornire un valore di default, e defi-
Sql Server 2005 migliora il supporto XML pre- nire un vincolo CHECK.
cedentemente offerto da Sql Server 2000 intro- Nell’esempio seguente viene creato un vin-
ducendo il tipo di dato nativo XML e metodi di colo CHECK sul campo di tipo XML che ve-
accesso ai dati XML, proponendo un modello rifica l’esistenza dell’elemento titolo. I me-
già da tempo consolidato nel DBMS Oracle – todi XML (di cui parleremo dopo) devono
rivale di sempre e oggi più che mai. essere forniti attraverso una user-defined
function:
Passato e presente di XML in Sql Server
Sql Server 2000 non aveva un tipo di dato CREATE FUNCTION udf_check_xml (@xml_col XML)
nativo XML. Si sopperiva a questa mancan- RETURNS bit AS
za con l’uso di campi di tipo TEXT oppure BEGIN
con la memorizzazione in formato relazio- RETURN (SELECT (@xml_col.exist(‘//titolo’)))
nale (sempre che la struttura del documen- END
to XML fosse sufficientemente semplice da GO
rendere possibile la memorizzazione del do-
cumento in tabelle normalizzate) [1]. Usare CREATE TABLE xml_tab
campi di tipo TEXT inibisce la possibilità di (
usare un linguaggio di query (XPath) sul do- id INT PRIMARY KEY,
cumento salvato, e con essa tutte le potenzia- xml_col XML NOT NULL DEFAULT(‘<libro><autore/><editore/
lità che XML è in grado di esprimere, mentre ><titolo/></libro>’)
la memorizzazione in formato relazionale co- CONSTRAINT CK_name CHECK (dbo.udf_check_xml (xml_col) = 1)
stringe a una sorta di conversione che implica )
un notevole lavoro e, comunque, fa perdere la GO
capacità gerarchica di lavorare con XML. Con
Sql Server 2005 si possono memorizzare do- Nel campo xml_col si può inserire un docu-
cumenti o frammenti XML in un tipo di dato mento o frammento XML well-formed (vedi
nativo XML (un frammento è un documento Riquadro 2), in caso contrario l’istruzione di
XML privo di una elemento radice). Ciò per- inserimento/aggiornamento fallisce:
mette di creare tabelle che registrino solo dati
XML o dati XML insieme a dati relazionali, INSERT INTO xml_tab VALUES(1, ‘<libro><autore/><editore/
validare dati XML attraverso gli schema, crea- ><titolo/></libro>’)
re indici sui dati XML, interrogare e modifi- INSERT INTO xml_tab VALUES(2, N’<autore/><editore/><titolo/>’)
care dati con XQuery, combinare i metodi di
interrogazione dei dati XML con query stan- --fallisce perché il frammento XML inserito non è well-formed
dard T-Sql per scrivere query che restituisca- INSERT INTO xml_tab VALUES(3, ‘<autore><editore></autore></
no dati relazionali insieme a dati XML. Ecco editore>’)
come creare un campo di tipo XML:

34 VBJ N. 65 - Settembre/Ottobre 2005


DATABASE

--fallisce perché viola il CHECK CONSTRAINT


Riquadro 1 Come nasce XML
INSERT INTO xml_tab VALUES(4, ‘<autore></autore><editore></
editore>’)
Nel 1996, l’XML Working Group creò XML (eXtensible
Il dato XML è registrato internamente in un Markup Language) basandosi sul meta-linguaggio SGML
(Standard Generalized Markup Language) costituito da
formato binario compresso per consentire un un insieme di regole per la creazione di linguaggi di
parsing più veloce rispetto ad una rappresen- marcatura (markup languages). XML scaturì dal tenta-
tivo di superare le limitazioni dell’HTML, altro linguaggio
tazione testuale. Quando il dato viene usato, è di marcatura derivato da SGML e divenuto popolarissi-
convertito in Varchar unicode (UTF-16). mo con la diffusione di internet. Infatti, l’HTML non è in
grado di presentare una strutturazione semanticamente
Per determinare la dimensione in byte effet- corretta delle informazioni, demanda l’elaborazione dei
tiva di un dato XML si può valutare la funzio- dati interamente ad altri linguaggi e, soprattutto, non è
ne DATALENGTH(): estendibile, costringendo i produttori di software a creare
propri standard. Fondamentalmente, rispetto all’HTML,
XML ha introdotto la gestione dei tag e degli attributi,
SELECT DATALENGTH (xml_col) FROM xml_tab una strutturazione di tipo gerarchico, e la validazione del
documento attraverso gli schema. L’XSL (eXtensible Style-
sheet Language), nato un anno dopo, ha reso possibile la
Il tipo di dato XML può essere adoperato ol- presentazione del documento XML attraverso fogli di stile
(style sheet) che si occupano di trasformare il documento
tre che per creare campi di tabella, anche per
XML per una sua più facile comprensione.
definire variabili e parametri di input e output
di stored procedure e user-defined function.

CREATE PROCEDURE sp_xml ( sione (superset) di XPath 2.0. Sql Server 2005
@x XML, supporta un sottoinsieme di XQuery 1.0 basa-
@y XML OUTPUT) to sul draft di Novembre 2003 [4]. I metodi ap-
AS plicabili sul dato XML sono i seguenti: exist(),
... query(), value(), nodes() e modify().
Il metodo exist() permette di valutare l’esi-
CREATE FUNCTION fn_xml ( stenza di elementi o attributi nelle clausole
@x NVARCHAR(max)) WHERE o nei CHECK CONSTRAINT, e re-
RETURNS XML stituisce il valore 1 se la valutazione ha esito
AS positivo, oppure 0 (zero) in caso di esito negati-
DECLARE @a XML vo. Di seguito, un esempio che fa uso di exist()
SET @a = @x nella clausola WHERE di una SELECT, allo
... scopo di selezionare le righe che presentano
RETURN @a nel campo XML denominato xml_col il valore
“Infomedia” in un qualsiasi attributo (@*) del-
Metodi del tipo di dato XML l’elemento “editore”, indipendentemente dalla
Per interrogare un dato XML estraendo un posizione (//) di quest’ultimo nel dato XML.
frammento o l’intero documento XML, è possi-
bile usare metodi esposti dal dato XML, i quali SELECT * FROM xml_tab
accettano come parametro di input un’espres- WHERE xml_col.exist(‘//editore[@*=”Infomedia”]’) = 1
sione XQuery. XQuery 1.0 è un linguaggio di
interrogazione standard di dati XML definito Il metodo query() restituisce un untyped
dal Wide Web Consortium (W3C) e basato su XML (documento o frammento), come risul-
XPath 2.0, un linguaggio di navigazione che tato della valutazione dell’espressione XQue-
usa una sintassi path-based per l’identificazio- ry su una lista di nodi XML. Il metodo va-
ne dei nodi di un documento XML. XQuery è lue() restituisce un dato scalare convertito
un linguaggio dichiarativo, tipizzato e funzio- nel tipo di dato T-SQL specificato come se-
nale, e trattasi, fondamentalmente, di un’esten- condo argomento della funzione. Di seguito

N. 65 - Settembre/Ottobre 2005 VBJ 35


DATABASE

due esempi che fanno uso di value() prima un database: una gestione fondamentalmente
nella SELECT e poi nella clausola WHERE. lenta del dato. Da qui la necessità di creare de-
gli indici su un campo di tipo XML. Sql Server
SELECT xml_col.value(‘/libro[1]/autore[1]’, ‘vachar(50)’) 2005 prevede la creazione di un indice primario
FROM xml_tab e fino a 248 indici secondari, a patto che esista
un indice primario (clustered) sulla chiave pri-
SELECT * FROM xml_tab maria della tabella. L’indice primario XML in-
WHERE xml_col.value(‘/libro[1]/autore[1]’, ‘varchar(50)’) = dicizza tutti i tag, i valori e i percorsi del con-
‘F.Quaratino’ tenuto di un campo XML. La chiave primaria
è usata per correlare le righe dell’indice XML
Il metodo nodes() scompone il contenuto di con le righe della tabella di database di cui fa
un tipo di dato XML restituendo ogni elemen- parte il campo stesso. Di seguito l’istruzione T-
to su una riga diversa. Poiché XQuery non de- SQL di creazione dell’indice XML primario sul
finisce una sintassi per la modifica dei docu- campo xml_col della tabella xml_tab
menti XML, Microsoft ha sviluppato un pro-
prio XML Data Modification Language (DML) CREATE PRIMARY XML INDEX xml_idx on xml_tab (xml_col)
[6] utilizzabile dal metodo modify(), il quale GO
consente la modifica del dato XML accettando
come parametro di input un’istruzione XML Dopo aver creato un indice primario sulla
DML di inserimento (insert), cancellazione colonna XML, è possibile creare indici XML
(delete) o sostituzione (replace value of). secondari per velocizzare particolari tipi di
query. Sono disponibili tre tipi di indici XML
Gli indici XML secondari: PATH, PROPERTY e VALUE:
La natura destrutturata di un dato XML de-
termina un inconveniente non irrilevante per • PATH per le ricerche di valori quando si
conosca l’esatto percorso dell’elemento o
attributo da cercare (per esempio: SELECT
Riquadro 2 Well-formed e Typed XML * FROM xml_tab WHERE xml_col.exist (‘/
libero[@anno = “2005”]’) = 1)
Un documento XML si dice well-formed(ben formato) • VALUE per le ricerche di valori quando
se osserva le seguenti regole sintattiche: non si conosca il nome o l’esatto percorso
• tutti gli elementi devono essere chiusi da un tag di dell’elemento o dell’attributo che contiene
chiusura (<persona></persona> o alternativamente tale valore ( è il caso delle cosiddette query
<persona/> se non c’è un testo e si tratta di un ele-
mento foglia);
“wildcard” come: /libro [@* = “poesie”], in
• tutti gli elementi devono essere annidati, nonché cui la query cerca ogni elemento <libro>
chiusi nella sequenza opposta a quella con cui sono che abbia un qualsiasi attributo che abbia
stati aperti, quindi non ammettendo sovrapposizioni
di elementi (<persona><nome></nome></persona> il valore “poesia” oppure (‘//libro/@genere[.
e non <persona><nome></persona></nome>); = “poesia”]’) = 1 in cui viene fornito un
• esiste un elemento root che contiene tutti gli altri;
• gli elementi sono case sensitive;
path parziale attraverso //)
• il valore degli attributi deve essere racchiuso tra • PROPERTY per le ricerche di valori spe-
apici o doppi apici.
cificando il nome di un elemento(/libro/
Un documento XML si dice typed (tipizzato) se associato autore)
ad uno schema, ovvero una struttura definita attraverso
una grammatica. Un documento XML si dice valido se
segue uno schema. È possibile fare in modo che un do- Ecco la sintassi per la creazione di indici XML
cumento XML sia sempre conforme alle regole stabilite secondari:
validandone i dati inseriti e le modifiche apportate alla
struttura del documento.
CREATE XML INDEX <index_name> on <table_name> (<xml_
column_name>)

36 VBJ N. 65 - Settembre/Ottobre 2005


DATABASE

USING XML INDEX <index_name> FOR [PATH | VALUE | PROPERTY] Bibliografia e Riferimenti
[1] G. Veneri – “DB e XML: prodotti”, Compu-
Conclusioni ter Programming/Infomedia, Maggio 2005
La combinazione di dati relazionali con dati [2] M. Simi – “Database XML nativi”, Compu-
XML offre nuove e interessanti possibilità nel- ter Programming/Infomedia, Maggio 2005
la modellazione dei dati, in grado di avvici- [3] XML:DB Initiative –
narsi maggiormente al mondo reale sempre http://xmldb-org.sourceforge.net
suscettibile di cambiamenti. L’introduzione di [4] http://www.w3.org/TR/xquery
un tipo di dato nativo XML consentirà anche [5] M. Nunn – “Extending XML in SQL Ser-
ai progettisti di database che adoperano Sql ver 2005”, Sql Server Magazine/Penton,
Server di progettare applicazioni molto più June 2005
flessibili, in quanto capaci di assorbire me- [6] P.Vithanala – “Introduction to XQuery
glio i cambiamenti che intervengono nel do- in SQL Server 2005”, Microsoft Corpora-
minio applicativo dell’applicazione, nel corso tion, June 2005 http://msdn.microsoft.com/
del suo intero ciclo di vita, grazie alla possibi- library/default.asp?url=/library/en-us/
lità di modellare i dati destrutturati. dnsql90/html/sql2k5_xqueryintro.asp
Occorre però fare attenzione a non farne un [7] S. Pal et al. – “XML Best Practices for Micro-
uso spregiudicato, dettato dalla moda del mo- soft SQL Server 2005”, Microsoft Corpora-
mento o dalla voglia di provare ad ogni costo tion, April 2004 http://msdn.microsoft.com/
il nuovo giocattolo messo a disposizione dal- SQL/archive/default.aspx?pull=/library/
la tecnologia emergente. Sarà, quindi, buo- en-us/dnsql90/html/sql25xmlbp.asp
na norma continuare ad usare il modello re- [8] S. Pal et al. – “XML Support in Microsoft
lazionale per la maggior parte dei dati, intro- SQL Server 2005”, Microsoft Corporation,
ducendo campi XML per ospitare informa- May 2005 http://msdn.microsoft.com/library/
zioni non obbligatorie o che potrebbero cam- default.asp?url=/library/en-us/dnsql90/html/
biare col tempo. sql2k5xml.asp

N. 65 - Settembre/Ottobre 2005 VBJ 37


.NET

Sviluppare Servizi
Windows con .NET
In passato scrivere Servizi Windows richiedeva la
conoscenza del C o del C++ ma con l’avvento del framework
.NET e dei suoi nuovi linguaggi C# e VB.NET, lo sviluppo
di questo tipo di applicazioni non è mai stato così semplice.
Servizi
Vediamo come scriverli, installarli e testarli

di Emanuele Delbono e Claudio Maccari

n ambiente Windows ci sono applicazioni più ta in esecuzione non appena il

I discrete di altre. Applicazioni che sono in ese-


cuzione ma rimangono in disparte, non si fan-
no vedere, talvolta giocano con il disco fisso e si
sistema operativo è avviato, in
una sessione separata da quel-
la dell’eventuale utente che si
fanno sentire ma per la maggior parte del tempo è loggato.
non ci accorgiamo della loro presenza. Analizziamo meglio questa de-
Eppure ci sono. Basta aprire il Task Manager per finizione:
vedere un lungo elenco di applicazioni in esecu-
zione… Ma chi le ha lanciate e soprattutto: cosa • Un Servizio Windows è un’ap-
fanno? plicazione che gira in back-
Per chi non lo avesse ancora capito, stiamo par- ground: vuol dire che il ser-
lando dei Servizi Windows, quelle particolari ap- vizio non ha interfaccia uten-
plicazioni che girano in background per svolgere te e la sua esecuzione non è
compiti “di sistema”. “visibile” agli utenti che uti-
Nel presente articolo analizzeremo cosa sono e lizzano il PC su cui gira;
come vengono implementati i Servizi, ne vedre- • Normalmente viene mandato
mo i vantaggi e i vincoli e vedremo cosa il .NET Fra- in esecuzione non appena il
mework mette a disposizione per realizzarne uno. sistema operativo è avviato:
infatti i servizi sono spesso
Cos’è un Servizio Windows utilizzati per quelle applica-
Prima di tutto diamo una definizione di servizio. zioni che devono sempre
Un Servizio Windows è un’applicazione che gira essere attive (ad esempio i
in background e che normalmente viene manda- server) per cui è importante
che siano attivati dal sistema
operativo senza che ci sia un
Emanuele Delbono si occupa di progettazione e sviluppo
di applicazioni su piattaforma Microsoft .NET. Svolge attività
utente che acceda e lo mandi
di formazione e partecipa come speaker a conferenze e in esecuzione;
workshop nazionali. • Sono in esecuzione in una
sessione separata da quello
Claudio Maccari, la programmazione per lui è una
dell’eventuale utente che si è
passione diventata un vero lavoro. Lavora come analista,
progettista e sviluppatore di applicazioni in particolar modo loggato: infatti se come dice-
su piattaforma .NET vamo sopra i servizi sono ap-

38 VBJ N. 65 - Settembre/Ottobre 2005


.NET

plicazioni silenziose
che vengono esegui-
te all’avvio del siste-
ma operativo, non è
necessario che un
utente sia logga-
to per mandarli in
esecuzione.

Quest’ultima carat-
teristica deve esse-
re tenuta ben presen-
te quando si sviluppa
un servizio: è fonda-
mentale che il servi-
zio non abbia interfac-
cia utente.
Siccome la maggior
parte dei servizi ven-
gono avviati automa-
ticamente dal siste-
ma operativo e gira-
no quindi in un desk-
top virtuale, cosa ac-
cadrebbe se il servizio
mostrasse una finestra
modale e aspettasse il
clic di un pulsante per
continuare la sua ese- Figura 1 La finestra delle proprietà del servizio
cuzione? Sarebbe cer-
tamente un problema
che renderebbe il ser-
vizio inutilizzabile. Queste caratteristiche fan- ce Control Manager (SCM), il Service Applica-
no si che il Servizio sia ottimo per compiti la tion (SA) e il Service Control Program (SCP).
cui esecuzione deve essere continua. Si pen- Il SCM è esso stesso un servizio (services.exe)
si ad esempio ad un server web: altro non che gira con privilegi di sistema e si occupa
è che un’applicazione che rimane in ascolto di gestire gli altri servizi avviandoli, ferman-
sulla porta 80 ed elabora le richieste che arri- doli, mettendoli in pausa, ecc…
vano dai client. Un’applicazione server (web, Il SA è il servizio vero e proprio quindi un
POP3, ecc…) è il tipico esempio di servizio, eseguibile avviato dal SCM che esegue le
tant’è che Microsoft stessa ha implementato operazioni per cui è stato scritto. Un SA avrà
il suo server web (Internet Information Ser- sempre almeno due eventi: OnStart e OnStop.
ver) come servizio (InetInfo.exe). Questi si verificheranno nel momento il cui il
servizio verrà rispettivamente avviato e fer-
Le componenti di un servizio mato. Il SCP è l’interfaccia che permette al-
L’infrastruttura che Windows mette a dispo- l’utente di interagire con il servizio inviando
sizione per l’implementazione e la gestione di comandi al SCM per avviare, fermare, modi-
un servizio è composta da 3 elementi: il Servi- ficare le credenziali, ecc… del servizio.

N. 65 - Settembre/Ottobre 2005 VBJ 39


.NET

Figura 2 La console per la gestione dei servizi

Di questi 3 componenti quello che il pro- OnStart, è chiamato dal SCM quando deve
grammatore andrà ad implementare (tra poco avviare il servizio e dovrà contenere il codice
vedremo come) è il servizio vero e proprio necessario allo startup delle operazioni che il
(SA) in quanto il SCM è un componente già servizio deve svolgere, il secondo invece vie-
presente nel sistema operativo e il SCP è an- ne chiamato quando il servizio viene fermato
ch’esso un’applicazione del pannello di con- e deve implementare i meccanismi di chiusu-
trollo di Windows, pertanto già disponibile (la ra e rilascio delle risorse.
troviamo nel Pannello di Controllo | Strumen- Inoltre il template di Visual Studio prepa-
ti di Amministrazione). ra il metodo Main per l’avvio del servizio da
Per la scrittura di un servizio, Visual Studio parte del SCM chiamando il metodo shared
.NET, ci viene incontro preparando parte del Run della classe ServiceBase:
codice necessario.
VS.NET crea una classe Service1 che eredita Dim ServicesToRun() As System.ServiceProcess.ServiceBase
da ServiceBase, classe base di tutti i servizi. ServicesToRun = New System.ServiceProcess.ServiceBase()
Di questa classe viene fatto l’override di al- {New Service1}
meno 2 metodi: OnStart e OnStop. Il primo, System.ServiceProcess.ServiceBase.Run(ServicesToRun)

40 VBJ N. 65 - Settembre/Ottobre 2005


.NET

Listato 1 La classe MSMQWatcher

Imports VBJService.MSQM
Public Class MSMQWatcher
Private myTimer As New System.Timers.Timer(10000)

Protected Overrides Sub OnStart(ByVal args() As String)


‘Threading.Thread.Sleep(15000) ‘da ultizzare solo in fase di debug
AddHandler myTimer.Elapsed, AddressOf myTimer_Elapsed
Try
EventLog.WriteEntry(String.Format(“Avviato il servizio di ricezione ordini Controllo eseguito ogni {0}
secondi”,myTimer.Interval 1000))
myTimer.Enabled = True
Catch ex As Exception
EventLog.WriteEntry(String.Format(“Errore durante l’avvio del servizio.{0}, Err.Description”))
End Try
End Sub

Protected Overrides Sub OnStop()


EventLog.WriteEntry(“Fermato il servizio di ricezione ordini”)
End Sub

Private Sub myTimer_Elapsed(ByVal pSender As Object, ByVal pArgs As System.Timers.ElapsedEventArgs)


Dim myQueue As New MSMQHelper
Dim myOrder As New Order
Try
myOrder = myQueue.ReceiveOrder()
EventLog.WriteEntry(String.Format(“Ricevuto l’ordine {0} del {1}”, myOrder.Id, myOrder.OrderDate))
Catch ex As Exception
EventLog.WriteEntry(String.Format(“Errore durante la ricezione degli ordini.{0}”, Err.Description))
End Try
End Sub
End Class

Questo è quanto serve per avere un servizio implementare il servizio. Grazie ai templa-
minimale. Oltre a questi metodi è possibile fare te di Visual Studio l’infrastruttra di codice
l’override di: OnPause, OnContinue, OnShu- necessaria la troveremo quasi tutta imple-
tDown, OnCustomCommand, OnPowerEvent mentata. Aperto Visual Studio, dal menù File
per gestire finemente le risposte del servizio scegliamo Progetto. Selezioniamo il proget-
agli eventi elencati. to di tipo Servizio Windows e lo chiamiamo
per esempio VBJService. Rinominiamo il file
Sviluppare il nostro primo Service1.vb in MSMQWatcher.vb.
Servizio Windows Per prima cosa possiamo notare che l’Inte-
Il servizio che andremo a creare avrà il com- grated Development Environment (IDE) ha
pito di processare gli ordini ricevuti. Gli or- già creato gli eventi fondamentali per il no-
dini sono creati da un’ipotetica applicazio- stro servizio ovvero OnStrat e OnStop.
ne dei nostri clienti ed inviati in una coda Nel Listato 1 aggiungiamo agli eventi car-
di messaggi presente sui nostri server e ge- dine il codice necessario per fare il log ed
stita da un’altro servizio: Microsoft Messa- utilizzare la piccola libreria (Listato 2) crea-
ge Queue (MSMQ). La nostra applicazione, ta per interfacciarsi con la coda degli ordini.
grazie al modello ad oggetti messo a dispo- Ricordiamo sempre che in un servizio l’inte-
sizione dal .NET framework nel namespa- razione con l’utente non può avere le solite
ce System.Messaging, ha il compito di pro- modalità come finestre e messaggi.
cessare i messaggi arrivati in coda. Iniziamo Ora che il nostro servizio è pronto per
quindi a scrivere qualche riga di codice per l’uso, si può avviare e fermare tramite

N. 65 - Settembre/Ottobre 2005 VBJ 41


.NET

Listato 2 La classe MSMQHelper

Imports System.Messaging

Public Class MSMQHelper

Dim myQueue As MessageQueue

Public Sub New()


Dim path As String
path = String.Format(“{0}\private$\OrderQueue”, My.Computer.Name)
‘se non esiste la coda la creo
If MessageQueue.Exists(path) = False Then
MessageQueue.Create(path, False)
End If
‘L’istanza della coda locale chiamata OrderQueue
myQueue = New MessageQueue(path)
‘crea un’istanza del formatter per convertire il body del messaggio in ordine
myQueue.Formatter = New XmlMessageFormatter(New Type() {GetType(Order)})
End Sub

Public Function ReceiveOrder() As Order


‘riceve il messaggio
Dim myMessage As Message = myQueue.Receive()
‘converte la proprietà Body in un’istanza di Order
Dim myOrder As Order = CType(myMessage.Body, Order)
Return myOrder
End Function

Public Sub SendOrder(ByVal order As Order)


SendOrder(order, True)
End Sub

Public Sub SendOrder(ByVal order As Order, ByVal recoverable As Boolean)


Dim myMessage As New Message
myMessage.Recoverable = recoverable ‘perdiamo in efficenza ma facciamo in modo che anche in caso di riavvio
del servizio i messaggi restino in coda
myMessage.Body = order
myQueue.Send(myMessage)
End Sub

End Class

SCP e, una volta avviato, grazie ad un ti- invece necessario prima installare il servizio
mer controlla la coda dei messaggi in at- e poi lanciarne l’esecuzione.
tesa di ordini, inserendo un record nel log Per installare Servizi Windows, il framework
degli eventi di Windows ogni volta che vie- mette a disposizione l’utilità da riga di co-
ne eseguita una di queste operazione. In- mando InstallUtil.exe. Prima di usare questo
somma cosa volere di più da un servizio? strumento però dobbiamo aggiungere ancora
Bene, allora perché non lanciarlo per vede- qualcosa al nostro servizio. Andiamo nella fi-
re se tutto è ok e cominciare a scrivere codi- nestra di design del servizio. Facciamo clic con
ce più interessante? Purtroppo, a differenza il tasto destro e quindi selezioniamo la voce
della maggior parte dei progetti creati in Vi- del menu Aggiungi programma d’installazio-
sual Studio .NET, i progetti di Servizio Win- ne. Per impostazione predefinita, al progetto
dows non possono essere eseguiti direttamen- sarà aggiunto un nuovo componente dal nome
te dall’ambiente di sviluppo premendo F5. È ProjectInstaller. Questo contiene i program-

42 VBJ N. 65 - Settembre/Ottobre 2005


.NET

Listato 3 Il generatore di ordini

Imports VBJService.MSQM

Module Module1

Sub Main()
Dim myQueue As New MSMQHelper()
Dim myOrder As New Order()
Try
‘ genero 10 ordine in circa 10 secondi per la felicità del direttore :P
For index As Integer = 1 To 10
myOrder.Id = DateTime.Now.Millisecond
myOrder.OrderDate = DateTime.Now
myQueue.SendOrder(myOrder)
Console.WriteLine(String.Format(“Inviato l’ordine {0} con data {1}”, myOrder.Id, myOrder.OrderDate))
Threading.Thread.Sleep(10)
Next
Catch err As Exception
Console.WriteLine(String.Format(“Si è verificato l’errore {0} “, err.Message))
End Try
Console.WriteLine(“Premere un tasto per continuare”)
Console.Read()

End Sub

End Module

mi d’installazione del servizio e del processo Messaggi). Bisogna quindi accertarsi di averlo
associato al servizio. Facendo doppio clic sul installato sulla nostra macchina. Ora il nostro
file appena aggiunto noteremo i due oggetti. servizio è installato. Possiamo avviarlo usan-
Per quanto riguarda il ProcessInstaller dovre- do SCP oppure usando il comando
mo prestare attenzione alla proprietà Account,
ovvero l’utente con cui sarà avviato il nostro VS Prompt
servizio: nel nostro caso dovrà essere “Local- net start msmqwatcher
Service”; mentre analizzando il componente
ServiceInstaller dovremo modificare le pro- Ora che il servizio è attivo possiamo con-
prietà ServiceName, Description e DisplayNa- trollare il log degli eventi.
me che saranno i valori visualizzati nel SCP. Troveremo un nuovo record che indica l’av-
Ora abbiamo davvero tutto quello che serve vio del nostro servizio. Per rendere le cose
per installare ed eseguire il servizio. Dopo aver più interessanti possiamo riempire la coda
compilato – per fare prima CTRL+SHIFT+B dei messaggi con qualche ordine da far pro-
– possiamo lanciare il Command Prompt di cessare al nostro servizio.
Visual Studio. Una volta posizionati nella Per far questo nell’esempio allegato all’ar-
cartella bin\debug del progetto che contiene ticolo troverete una semplice applicazione
l’eseguibile fresco di compilazione e lancia- console che una volta lanciata inserisce 10
mo il comando messaggi nella coda OrderQueue (Listato 3).
Nel momento in cui il servizio trova i mes-
VS Prompt saggi può cominciare a fare il suo vero la-
InstallUtil vbjservice.exe voro. Per verificarlo controlliamo ancora il
log degli eventi dove avremo un nuovo re-
Ricordiamoci che la nostra applicazione usa cord per ogni ordine processato dal servizio.
il servizio MSMQ [1] (in italiano Accodamento Una volta processati tutti gli ordini possia-

N. 65 - Settembre/Ottobre 2005 VBJ 43


.NET

mo fermare il nostro servizio dal SCP op- ‘Max 30 secondi altrimenti il servizio va in timeout
pure usando il comando Threading.Thread.Sleep(15000)

VS Prompt Questo ci darà 15 secondi di tempo per ag-


net stop msmqwatcher ganciare il processo del servizio al debugger
di Visual Studio. Ricordiamoci di non andare
Debug oltre i 30 secondi altrimenti l’avvio del servi-
Il nostro servizio è talmente semplice da non zio darà errore di timeout. Così facendo bi-
richiede un debug; in un caso reale più com- sogna ricordarsi di commentare l’istruzione
plesso però potremmo avere bisogno di que- prima del rilascio in produzione.
st’importante feature messa a disposizione dal Una tecnica alternativa che permette di de-
nostro ambiente di sviluppo. Per questo è bene buggare interamente il servizio, compreso il
sapere come fare in caso di bisogno; infatti a metodo OnStart, è quello di scrivere un’ap-
differenza delle altre applicazioni, se da Visual plicazione Windows Forms che assume il ruo-
Studio.NET premiamo F5 per mandare in ese- lo di Service Control Manager, cioè avvia il
cuzione il servizio, per il debugging non accade servizio, lo ferma, ecc…
nulla. Il debug di un servizio è un’operazione L’applicazione Windows Forms avrà inter-
leggermente più complessa. L’idea è di utilizza- faccia utente e utilizzerà il servizio come se
re il debugger dei processi di VS.NET per ag- fosse una sua libreria chiamando i metodi
ganciarsi al servizio creato, quindi si inserisce OnStart, OnStop, ecc…in questo modo ogni
un breakpoint nel punto in cui vogliamo fer- eventuale errore sul metodo OnStart può es-
mare il programma (non nel metodo OnStart) sere intercettato visto che stiamo debuggan-
e poi facciamo partire il servizio come visto in do una normale applicazione Windows.
precedenza. A questo punto dovremo ritornare
nell’IDE e scegliere Processi dal menu Debug. Conclusioni
Sarà visualizzata la finestra di dialogo Proces- Come abbiamo visto, lo sviluppo di un ser-
si. Verificheremo che il flag Mostra processi di vizio non è molto diverso da altri tipi appli-
sistema sia attivo. cazione Windows.
Nella sezione Processi disponibili, faremo Quindi se da un lato la nostra applicazio-
clic sul processo del servizio, e ci aggancere- ne può scalare di molto, dall’altra bisogna
mo tramite il pulsante Connetti. A questo pun- prima considerare alcuni punti fondamen-
to siamo in modalità di debug e l’esecuzione tali, quali l’iterazione con l’utente e la ge-
si interromperà sul breakpoint settato prima. stione degli errori.
Questa tecnica, benché permetta il debug del Una nota dolente può essere l’esecuzione
servizio, ha alcune limitazioni. Infatti può ca- del debug.
pitare che il servizio abbia un bug nel meto- Per ovviare a questo inconveniente è buo-
do OnStart. na regola spostare la logica applicativa in
Quando andiamo ad agganciare il processo un componente esterno – noi l’abbiamo fatto
tramite VS.NET, il metodo OnStart è stato già con la libreria che fa da proxy con MSMQ –
eseguito e intercettare gli errori in quel meto- e testarlo separatamente tramite strumenti
do risulta quasi impossibile. Qualora fosse ne- di Unit Testing (per es. NUnit).
cessario eseguire il debug dell’evento OnStart
è possibile utilizzare una “trucchetto” molto Riferimenti
semplice e veloce. La prima istruzione del me- [1] Microsoft TechNet – Accodamento mes-
todo OnStart dovrà essere saggi http://www.microsoft.com/technet/
prodtechnol/windowsserver2003/it/library/
VB.NET ServerHelp/192eb6e0-e4ac-4dd0-bc44-
‘da utilizzare solo in fase di debug dd26a43f5fa8.mspx

44 VBJ N. 65 - Settembre/Ottobre 2005


.NET

SOAP Messaging
con WSE WSE

Vediamo le principali caratteristiche di Microsoft Web Services Enhancements


dal punto di vista del SOAP Messaging.

di Paolo Pialorsi

icrosoft Web Services Enhancements plessi come Visual Studio .NET

M (WSE, si pronuncia “uisi”) è una libre-


ria per estendere il motore di Web Ser-
vice di base del Framework .NET. Giunta alla ver-
e il .NET Framework. Negli ul-
timi 3 anni abbiamo utilizzato
.NET Framework 1.x e solo ora
sione 2.0 Service Pack 3 [3], affiancata nell’ultimo sta per vedere la luce il .NET Fra-
periodo da una Technology Preview della versione mework 2.0. Nel frattempo sono
3.0, rappresenta ormai un prodotto maturo e stabi- uscite diverse release di WSE di
le per la creazione di servizi SOAP in architettura cui 2 maggiori (WSE 1.0 e WSE
Service Oriented ([1] e [2]). In questo articolo ve- 2.0) e diverse minori (vari Servi-
dremo come utilizzare WSE2 per creare applicazio- ce Pack), oltre a un’anteprima di
ni in grado di scambiarsi messaggi SOAP. WSE 3.0. Tutte queste versioni,
rilasciate in meno di due anni,
Perché WSE? sono il frutto della rapida e incon-
La prima domanda che viene generalmente posta trollabile crescita di WSA (Web
quando si parla di WSE è: “Perchè WSE?”. In .NET Services Architecture) e di tutte
abbiamo infatti un motore per la creazione di Web le numerose specifiche (WS-Se-
Service, i cosiddetti Web Service ASMX, e per mol- curity, WS-Addressing, WS-Atta-
ti non è chiara la ragione per cui debba esistere una chments, ecc.) ad essa collegate.
libreria aggiuntiva che li estende, a volte rappresen- Potremmo descrivere WSE come
tandone un’alternativa. WSE nasce con l’obiettivo lo sforzo, da parte di Microsoft,
di fornire il supporto alle specifiche più moderne di rimanere allineata con l’evo-
relative a SOAP e ai (Web) Service. Si tratta di una luzione tecnologica della specie
libreria esterna al motore degli ASMX, in quanto (SOAP). Dall’altro lato, proprio
deve essere in grado di evolvere rapidamente e agil- per come è pensato, WSE è da
mente, senza sottostare alle regole di validazione e utilizzare essendo consapevoli
rilascio del codice cui sono soggetti prodotti com- del fatto che ogni 6 mesi o al mas-
simo ogni anno dovremo riscri-
vere parte del nostro codice, per
aggiornarlo a una nuova versio-
ne della libreria. WSE2 e WSE1
infatti non sono compatibili tra
Paolo Pialorsi è un consulente e autore specializzato nello loro, né come codice e funzionali-
sviluppo di Web Service e soluzioni Web con il Framework
.NET di Microsoft. Lavora nell’omonima società Pialorsi tà, né in termini di compatibilità
Sistemi S.r.l. e fa parte del gruppo DevLeap. Mantiene un binaria dei messaggi che viaggia-
blog all’indirizzo: http://blogs.devleap.com/paolo/. no sul cavo. Anche il passaggio

N. 65 - Settembre/Ottobre 2005 VBJ 45


.NET

da WSE2 a WSE3, quando avverrà, non è ga-


rantito che sia completamente indolore.
Occupandoci della versione attualmente rila-
sciata, WSE2 supporta le seguenti specifiche:

• SOAP 1.1
• WSDL
• WS-Security
• WS-SecurityPolicy
• WS-SecureConversation
• WS-Trust
• WS-Referral
Figura 1 Flusso di un messaggio SOAP attraverso
• WS-Addressing una Pipeline di WSE
• WS-Policy
• DIME
• WS-Attachments prevede un’architettura pesantemente basa-
ta sul concetto di messaggio, che essendo un
La preview di WSE3, ad oggi e per comple- messaggio SOAP assume la forma di un og-
tezza, sostituisce il supporto agli allegati nei getto di tipo SoapEnvelope. Una SoapEnve-
messaggi SOAP, che lo scorso anno erano ge- lope non è altro che una classe, derivata da
stiti con WS-Attachments e DIME, con la com- System.Xml.XmlDocument, che fornisce al-
patibilità con MTOM (Message Transmission cune funzionalità di uso ricorrente per la ge-
Optimization Mechanism [5]), oltre a fornire stione di un messaggio SOAP. Per esempio at-
la possibilità di essere utilizzato con .NET 2.0. traverso un’istanza di SoapEnvelope possiamo
Probabilmente WSE4 non vedrà mai la luce, accedere direttamente al Body e agli Header
infatti nel 2006 dovrebbe essere rilasciato In- del messaggio SOAP. Sempre dalla SoapEn-
digo [7] che andrà a sostituirsi a tutte le at- velope abbiamo accesso a una serie di meta-
tuali tecnologie di comunicazione e che do- informazioni sul messaggio, relative alla sicu-
vrebbe (il condizionale è d’obbligo) essere in rezza, al routing, al messaging, agli eventuali
grado di “parlare” con WSE3. file allegati al messaggio, ecc.
Ogni volta che un messaggio SOAP viene
gestito da WSE, esso attraversa una pipeline
Microsoft WSE è una libre- di filtri, detti SoapFilter, che processano sia
in ingresso (SoapInputFilters) che in uscita
ria per estendere il motore (SoapOutputFilters) le singole SoapEnvelo-
di Web Service di base del pe (Figura 1). Esistono dei SoapFilter prede-
finiti come quelli per gestire la sicurezza dei
Framework .NET messaggi, il loro instradamento e in caso di
esigenza il logging a fini di diagnostica. Pos-
siamo creare nostri SoapFilter derivando da
SoapEnvelope - il cuore di WSE classi base molto comode.
Per utilizzare WSE dobbiamo innanzitutto Le SoapEnvelope attraversano queste pipe-
scaricarlo da MSDN [3] - consiglio l’installa- line in quanto il motore di WSE prevede il
zione di tipo Visual Studio .NET Developer, concetto di SoapPort, della quale esistono di-
per avere un addin di configurazione di WSE a verse implementazioni che vedremo nel cor-
disposizione nell’IDE di Visual Studio .NET - so dell’articolo. Ad ogni SoapPort sono asso-
e referenziarlo nei nostri progetti, cercando la ciate una lista (Pipeline) di filtri e un cana-
class library Microsoft.Web.Services2.dll. WSE le (Channel). L’architettura di messagging di

46 VBJ N. 65 - Settembre/Ottobre 2005


.NET

WSE è pensata per essere utilizzata in due SOAP sono intercambiabili ed estendibili, ri-
differenti modalità: spetto all’architettura del singolo servizio.
Esistono diverse implementazioni per vari
• affiancata al motore ASMX per estender- protocolli di uso comune. Già WSE2 offre il
lo, sfruttando una SoapExtension [6] lato supporto per HTTP, TCP e un protocollo IN-
server e una specializzazione di SoapHt- PROCess per le comunicazione all’interno di
tpClientProtocol lato client; uno stesso AppDomain. Esistono inoltre sulla
• come alternativa ad ASMX, utilizzando un rete implementazioni indipendenti di MSMQ,
motore di comunicazione ad hoc. UDP, SMTP, ecc. Quando sviluppiamo i servi-
zi possiamo prescindere dal protocollo di tra-
Il fatto che WSE2 esponga le sue funzionalità sporto che andremo a utilizzare per esporli, con
sia come aggiunta al motore degli ASMX, che un approccio pienamento SOA. Solo nel mo-
come sistema alternativo ad essi, ci consente di mento in cui vorremo esporre i servizi dovre-
creare server e client di servizi SOAP senza bi- mo preoccuparci di definire un punto di acces-
sogno di un server IIS e/o ASP.NET. Da questo so (EndpointReference) e configurarlo affiché
momento in poi ci concentreremo sullo scambio utilizzi un determinato protocollo.
di messaggi SOAP, per utilizzare WSE2 come in-
frastruttura di comunicazione tra processi, ser- SoapSender
vizi e sistemi senza utilizzare IIS e ASP.NET. Vediamo un primo esempio di utilizzo di Soa-
Questo ci consente di avere un approccio com- pReceiver e SoapSender, sfruttando il proto-
pletamente orientato a SOA. collo TCP. Immaginiamo di voler inviare tra-
mite SOAP Messaging un oggetto che rappre-
Soap Messaging senta un ordine. Dobbiamo innanzitutto crea-
Il motore di comunicazione di WSE2 si basa re una SoapEnvelope che descriva il messag-
sull’uso di classi derivate da SoapPort (Figu- gio da inviare:
ra 2). Nello specifico esistono due modalità
di comunicazione, che corrispondono a due C#
differenti paradigmi di dialogo: // Nella variabile order immagino di avere i dati di un
ordine
• SoapReceiver/SoapSender: prevede un si- Order order = new Order();
stema di scambio paritetico di messaggi order.IdOrder = 10;
SOAP. Si utilizza quando si devono creare order.Description = “Ordine dimostrativo 10”;
sistemi di comunicazione monodirezionale,
oppure peer-to-peer ovvero sistemi di co- SoapEnvelope envelope = new SoapEnvelope();
municazione asincrona, dove il client (che
di solito viene chiamato “endpoint” e non
più client) può richiamare l’altro endpoint
(quello che tradizionalmente sarebbe il ser-
ver). In questo modo si possono creare dia-
loghi asincroni.
• SoapService/SoapClient: pensato per un
approccio più classico, dove esiste un ser-
ver che espone dei servizi, utilizzati dai
client, che si limitano ad invocarli e atten-
derne il risultato.
Figura 2 Schema funzionale di una SoapPort in
Aspetto chiave di questa architettura è il fat- WSE
to che i protocolli di trasporto dei messaggi

N. 65 - Settembre/Ottobre 2005 VBJ 47


.NET

envelope.CreateBody(); </soap:Body>
envelope.SetBodyObject(order, “http://schemas.devleap.com/ </soap:Envelope>
order”);
Si può notare la struttura di un classico mes-
Con queste prime righe stiamo creando un saggio SOAP, costituito dalla Envelope, dal
oggetto DOM XML - ricordiamoci che SoapEn- Body e dal contenuto (nel nostro caso l’ordi-
velope deriva da XmlDocument - che avrà la ne). A questo punto possiamo creare un og-
struttura di una SOAP Evenlope e conterrà getto SoapSender, per inviare il messaggio ad
al suo interno l’oggetto order, serializzato con un altro EndpointReference (cioè al destina-
XmlSerializer, che è lo stesso motore di seria- tario del messaggio):
lizzazione che utilizzano anche gli ASMX. Po-
tremmo in alternativa costruire il contenuto C#
del messaggio SOAP manualmente, creando envelope.Context.Addressing.Action = new Action(“urn:
i singoli nodi XML all’interno del Body del sendOrder”);
messaggio SOAP.
Come si vede abbiamo quindi la massima EndpointReference ep = new EndpointReference(
versatilità rispetto alla gestione del contenu- new Uri(“soap.tcp://localhost:34000/DemoReceiver”));
to del messaggio SOAP, potendo sfruttare al SoapSender sender = new SoapSender(ep);
massimo il SOAP messaging. Per verificare
cosa sta succedendo dietro le quinte, imma- sender.Send(envelope);
ginando che il nostro ordine sia definito nel
modo seguente: Si vede che dobbiamo per prima cosa crea-
re un EndpointReference che rappresenterà
C# il riferimento al servizio da raggiungere, com-
public class Order presi il protocollo di comunicazione (soap.tcp
{ in questo caso) e la porta di comunicazione ri-
public Int32 IdOrder; servata a questo scambio di messaggi.
public String Description; Inoltre è di fondamentale importanza l’in-
} dicazione della Action SOAP del messaggio
che stiamo inviando, per consentire al desti-
possiamo provare a salvare la SoapEnvelope natario di capire cosa gli stiamo chiedendo
su disco e vederne il contenuto XML: o dicendo.
La Action, esattamente come tutte le altre
C# meta-informazioni di sicurezza, routing, ecc.
envelope.Save(“order.soap.xml”); si configura attraverso una proprietà specia-
le della SoapEnvelope, di nome Context, che
rappresenta un riferimento al contesto della
XML (SOAP) singola richiesta o risposta SOAP.
<?xml version=”1.0” encoding=”utf-8”?> È all’interno di Context che troviamo pro-
<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/ prietà come Security, Addressing, Attachmen-
soap/envelope/”> ts, ecc. che ci permettono di configurare ap-
<soap:Body> punto il contesto di dialogo SOAP.
<Order xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” SoapReceiver
xmlns=”http://schemas.devleap.com/order”> Per ricevere il messaggio appena creato ed
<IdOrder>10</IdOrder> inviato dal SoapSender, dobbiamo dichiara-
<Description>Ordine dimostrativo 10</Description> re una classe derivata da SoapReceiver, della
</Order> quale dovremo ridefinire il metodo Receive:

48 VBJ N. 65 - Settembre/Ottobre 2005


.NET

C# ne Windows Forms o ancor meglio un servizio


public class DemoReceiver: SoapReceiver del sistema operativo, che rimangano in esecu-
{ zione e quindi in ascolto per i nostri messaggi
protected override void Receive(SoapEnvelope envelope) SOAP. Il messaggio stampato a Console conter-
{ rà qualche informazione in più rispetto a quel-
// Il SoapEnvelope è anche un XMlDocument lo salvato in precedenza, principalmente per il
// quindi so come cercare e sfogliare fatto che il messaggio questa volta sarà passato
// i nodi al suo interno attraverso il Channel della SoapPort di uscita
envelope.Save(Console.Out); e poi di ingresso, subendo quindi l’azione dei
} vari SoapFilter configurati nelle rispettive Pi-
} peline (Output prima e Input poi), che aggiun-
gono, verificano e tolgono informazioni associa-
In questo esempio ci limitiamo a salvare sul- te a diversi namespace XML. Si tratta proprio
la finestra Console del receiver il messaggio dei namespace XML che troviamo aggiunti al
ricevuto dal sender. In condizioni normali do- messaggio finale.
vremmo valutare la Action (envelope.Context.
Addressing.Action) e decidere il da farsi. Infi- Rispondere ai messaggi
ne dobbiamo registrare, lato server, il fatto che Se volessimo a questo punto rispondere al
vogliamo stare in ascolto di messaggi SOAP sender, dovremmo avere anche dal suo lato un
destinati al nostro SoapReceiver particolare: oggetto derivato da SoapReceiver e posto in
ascolto su un determinato EndpointReferen-
C# ce. Il sender potrebbe per esempio dire:
public class ReceiverHostCode
{ C#
static void Main() envelope.Context.Addressing.ReplyTo = new ReplyTo(new
{ Uri(“soap.tcp://localhost:35000/Sender”));
EndpointReference ep = new EndpointReference(
new Uri(“soap.tcp://localhost:34000/DemoReceiver/ “)); per comunicare al receiver l’indirizzo al qua-
SoapReceivers.Add(ep, typeof(DemoReceiver)); le inviare eventuali risposte (ReplyTo).
Il receiver dal canto suo potrebbe risponde-
Console.ReadLine(); re chiedendo alla SoapEnvelope di generare
} la risposta per il messaggio appena ricevuto,
} nel modo seguente:

Come si vede ci appoggiamo alla classe C#


SoapReceivers che esponde un metodo sta- SoapEnvelope response = new SoapEnvelope();
tico Add, che ci consente di aggiungere un response.SetBodyObject(orderResponse, “http://
Receiver su un determinato EndpointRefe- schemas.devleap.com/Response”);
rence. Da notare che con un singolo Recei- envelope.Context.Addressing.SetResponseHeaders(response.
ver potremmo stare in ascolto su diversi En- Context.Addressing);
dpointReference, quindi anche su diversi pro-
tocolli e indirizzi. In pratica dobbiamo creare una nuova Soa-
Dal momento che il motore di WSE rimane pEnvelope, inserire al suo interno la risposta
in ascolto su un thread diverso da quello prin- (orderResponse nel nostro esempio) e chiede-
cipale della nostra applicazione, dobbiamo so- re alla richiesta di configurare l’indirizzamen-
spendere il progamma host aspettando la pres- to SOAP della risposta. L’oggetto SoapEnvelo-
sione del tasto INVIO a Console. In condizioni pe ricevuto come richiesta compilerà i cam-
di regime ci converrà realizzare un’applicazio- pi corretti della risposta, per consentire al de-

N. 65 - Settembre/Ottobre 2005 VBJ 49


.NET

stinatario di capire che il messaggio inviato- Si noti che l’attributo SoapService riporta il
gli costituisce una risposta per il precedente namespace XML del SOAP Service che stiamo
messaggio. Non ci resterà quindi altro da fare definendo, mentre l’attributo SoapMethod in-
che inviare la risposta utilizzando una classe dica il nome della Action dell’operazione che
SoapSender, come abbiamo già visto. descrive.
L’endpoint che ha originato il dialogo potrà Mettendo un SoapReceiver in ascolto su un
riconoscere la risposta in base al fatto che determinato EndpointReference e protocollo,
tramite WS-Addressing i messaggi SOAP per questo servizio, siamo già pronti a riceve-
possono riportare l’indicazione di un Messa- re richieste a lui destinate.
geID, che rappresenta univocamente i singo-
li messaggi. C#
Inoltre esiste una proprietà, sempre di WS- EndpointReference ep = new EndpointReference(
Addressing, di nome RelatesTo che mette in new Uri(“soap.tcp://localhost:34000/DemoService”));
relazione tra loro i messaggi.
SoapReceivers.Add(ep, typeof(DemoService));
SoapClient e SoapService
Se la nostra esigenza è quella di realizza- Qualora volessimo avere un’unica istanza di
re un paradigma di dialogo di tipo richiesta/ servizio in ascolto per tutte le richieste, per
risposta, possiamo utilizzare direttamente le esempio per condividere informazioni di stato,
classi SoapClient e SoapService, che altro potremmo assegnare alla classe SoapReceivers
non sono che specializzazioni di SoapSender l’EndpointReference unitamente ad una parti-
e SoapReceiver. colare istanza della classe SoapService, invece
In particolare SoapService rappresenta che fornire solo il tipo (typeof) generico.
l’equivalente di un WebService ASMX in WSE
e un SoapClient è ciò che si ottiene costruen- C#
do una sorta di Web Reference WSE verso un EndpointReference ep = new EndpointReference(
servizio, anche non necessariamente esposto new Uri(“soap.tcp://localhost:34000/DemoService”));
con WSE. Partiamo questa volta dall’imple-
mentazione del servizio. Dobbiamo definire SoapReceivers.Add(ep, new DemoService());
una classe che derivi dalla classe base Soap-
Service e che presenti l’attributo .NET Soap- Se avessimo sviluppato un WebService con
Service al posto del classico WebService degli dei WebMethod, a questo punto potremmo
ASMX. Quindi possiamo decorare i singoli me- chiedere a Visual Studio .NET di creare una
todi del servizio con l’attributo SoapMethod Web Reference verso la URL del servizio. Per
invece di WebMethod. Ecco un esempio: altro Visual Studio .NET, quando creiamo del-
le Web Reference, non fa altro che eseguire lo
C# stesso codice che potremmo eseguire autono-
[SoapService(“http://schemas.devleap.com/DemoService/”)] mamente chiamando dal prompt dei comandi il
public class DemoService: SoapService tool WSDL.EXE. Ecco che WSE2 fornisce qual-
{ cosa di molto simile: WSEWSDL2.EXE. Possia-
[SoapMethod(“urn:SendOrder”)] mo invocarlo dandogli come argomento la URI
public String SendOrder(Order order) di un servizio, per ottenere in cambio il codice
{ di un SoapClient pronto da istanziare.
return(String.Format(“Ordine {0} ricevuto!”,
order.IdOrder)); Command Prompt
} C:\Program Files\Microsoft WSE\v2.0\Tools\Wsdl\WseWsdl2.exe
} URI-Servizio file.cs

50 VBJ N. 65 - Settembre/Ottobre 2005


.NET

Nel nostro caso avremo: pena generato e poi utilizzare la classe De-
moService creata:
Command Prompt
WseWsdl2.exe soap.tcp://localhost:34000/DemoService C#
DemoServiceClient.cs DemoService svc = new DemoService();

Ed ecco che verrà auto-generato per noi un Order order = new Order();
file di codice che descriverà la classe Order order.IdOrder = 10;
e il SoapClient del servizio. order.Description = “Ordine 10”;
Per brevità riporto solo le parti salienti del
codice e rimando agli allegati all’articolo per Console.WriteLine(svc.SendOrder(order));
i dettagli: Console.ReadLine();

C# Conclusioni
[SoapService(“http://schemas.devleap.com/DemoService/”)] Spero con questi esempi di aver stimolato la
public class DemoService : SoapClient vostra fantasia e di avervi fatto venire la vo-
{ glia di provare a creare qualche applicazione
public DemoService() : base( new Uri(“soap.tcp: in grado di comunicare tramite SOAP con al-
//localhost:34000/DemoService”) ) tri servizi o sistemi.
{ È doveroso sottolineare che, dal punto di vi-
} sta della interoperabilità tra piattaforme e si-
stemi, ad oggi il SOAP Messaging di WSE2 è
[SoapMethod(“urn:SendOrder”)] utilizzabile solo da WSE2 stesso.
public System.String SendOder( Order request ) Se vogliamo utilizzare WSE per rivolgerci
{ ad altre piattaforme dobbiamo pensarlo solo
return (System.String)base.SendRequestResponse(“SendOrder”, come estensione di ASP.NET e dei Web Servi-
request).GetBodyObject( typeof(System.String), SoapService ce ASMX. Ciò nonostante il SOAP Messaging
Attribute.TargetNamespace); risulta molto comodo in diverse situazioni in
} cui si vogliono mettere in comunicazione tra
// omissis... loro applicazioni .NET sfruttando le potenzia-
} lità di SOAP.

Il codice contiene la definizione di una Bibliografia


classe di nome DemoService, che deriva [1] P. Pialorsi – “Service Oriented Architecture”,
da SoapClient ed espone un metodo Sen- Visual Basic Journal n° 61
dOrder. Si noti che sia la classe che il me- [2] P. Pialorsi – “SOA e il .NET Framework”,
todo sono decorati anche lato client rispetti- Visual Basic Journal n° 62
vamente dagli attributi SoapService e Soap-
Method. Riferimenti
Non entro nel merito dell’implementazione [3] http://msdn.microsoft.com/webservices/
del metodo SendOrder, ma sottolineo soltan- [4] http://www.devleap.com/wse2/
to il fatto che WSEWSDL2.EXE ha generato [5] http://www.w3.org/TR/2005/REC-soap12-
per noi anche i metodi BeginSendOrder ed mtom-20050125/
EndSendOrder, per consentirci di invocare [6] http://www.devleap.com/SchedaArticolo.a
il SoapService in modo asincrono, lato client spx?IdArticolo=10450
[8]. Una nostra applicazione client, che vo- [7] http://winfx.msdn.microsoft.com/
glia utilizzare il SoapService, dovrà limitar- [8] http://www.devleap.com/SchedaArticolo.a
si ad includere o referenziare il codice ap- spx?IdArticolo=10610

N. 65 - Settembre/Ottobre 2005 VBJ 51


.NET TOOLS
DTSBackup 2000 Una volta impostato il server sorgente viene espo-
di Angelo Ossola sto l’elenco di tutti i DTS presenti nella basi di dati
Probabile, anche se poco auspicabile, scenario dal quale è possibile selezionare quelli per i quali
aziendale: un sistema basato su Microsoft SQL 2000 si vuole eseguire il backup. A questo punto è ne-
esegue trasferimenti ed elaborazioni di dati attra- cessario impostare la destinazione del backup ed è
verso dei DTS, fondamentali per la realtà produtti- qui che la versatilità del programma balza agli oc-
va, tra piattaforme eterogenee (ad esempio da e ver- chi dell’utente: possiamo impostare un altro server
so AS400), magari schedulati automaticamente per nel quale salvare i DTS (a questo punto possiamo
girare in fase notturna. Un “bel” giorno: crash del usare questo tool anche per copiare DTS tra un ser-
server! Si rende necessario rimettere in piedi tut- ver ed un altro), salvarlo in un file con estensione
to il sistema. Ovviamente, lo spero, nessuno è così .dts, in uno Structured Storage File oppure in un
scellerato da non avere backup dei dati periodici e Meta Data Services Packages. Avviando il trasfe-
delle applicazioni fondamentali al buon funziona- rimento dei DTS viene proposto un report di fun-
mento dell’ambiente che deve gestire. I backup, se zionamento in puro stile SQL 2000 nel quale viene
fatti a regola d’arte, consentono di ripristinare tutti i proposto l’esito di ogni operazione eseguita nel job
database in modo completo e rigoroso ma (c’è sem- appena avviato.
pre un ma …) c’è un problema: i DTS? Non ci sono Vi sono, inoltre, interessanti opzioni che rendono
nei backup! Sfido chiunque a riscriverli in un mo- questo strumento ancor più elastico e flessibile, tra
mento del genere senza commettere qualche errore cui la possibilità di inserire la password da usare
o dimenticanza. La soluzione veramente facile ed con package criptati, esportare la lista dei DTS in
immediata ce la propone DTSBackup, un tool tanto formato txt e, ancor più utile in determinate circo-
semplice da usare quanto efficace rispetto al proble- stanze, la possibilità di “pilotare” il software anche
ma appena esposto. Av- da riga di comando. Dalla
viando il programma ed linea di comando è pos-
osservando l’ambiente sibile impostare i server
di lavoro possiamo im- sorgente e destinazione,
mediatamente intuire la la modalità di connessio-
logica davvero “easy” con ne ai server, username e
la quale è stata svilup- password per le varie
pata l’applicazione; pre- connessioni ed altro an-
mendo il pulsante per la cora. Da sottolineare, in-
selezione della sorgente fine, anche la possibili-
dei dati ci viene presen- tà di criptare anche nel-
tata una finestra di dialo- la linea di comando sia
go che risulterà molto fa- lo username che la pas-
miliare a tutti gli avvezzi sword. Per quanto con-
di Microsoft SQL 2000 e cerne, invece, l’operazio-
che permette di selezio- ne di restore essa avviene
nare il server (o la named in modo del tutto analo-
instance) SQL. go, seppur a ruoli ovvia-

52 VBJ N. 65 - Settembre/Ottobre 2005


.NET TOOLS

mente invertiti, rispetto a quella di backup. Tiran- to usare per risparmiare tempo e per avere un
do le somme siamo in presenza di un tool, tra l’al- risultato davvero congruente con la formatta-
tro frequentemente aggiornato dai suoi creatori, che zione del codice usata negli ambienti di svilup-
sopperisce ad una mancanza dell’enterprise mana- po. Questo tool, free, e scaricabile velocemente
ger di SQL 2000 in modo semplice ed efficace. dal sito di riferimento (sono solo circa 50KB) si
presenta con soli due file: l’eseguibile ed una
dll a corredo.
Prodotto
DTSBackup 2000 UI Lanciando il programma siamo accolti in un
ambiente decisamente user-friendly, come si
Url di riferimento
http://www.sqldts.com/dtsbackup/ può vedere dall’immagine, che è essenzialmen-
te composto da quattro pulsanti e da un com-
Stato Release
1.1.6 boBox. Nell’elenco presente è possibile sceglie-
re il linguaggio del file sorgente che andremo
Semplicità d’uso 
L’interfaccia in puro stile Microsoft SQL 2000 permette ai vete-
a caricare e per il quale vogliamo sviluppare la
rani di questo ambiente di essere subito a proprio agio con que- pagina HTML; i linguaggi che vengono gestiti
sta applicazione. dal programma sono diversi: C#, VB.NET, VB
Utilità  Script, Java Script, C++, SQL, Cascading Stye
È un tool che sopperisce ad una insufficienza dell’enterprise ma- Sheet, Cobol, Algol e i linguaggi di markup qua-
nager in modo davvero apprezzabile.
li ad esempio HTML ed e vari dialetti derivati
Qualità prodotto  dall’XML (XSL, VXML, ecc.).
Software che implementa ogni sfaccettatura della funzionalità per
Una volta scelto il linguaggio con il quale vo-
cui è stato progettato con elevata stabilità ed efficienza.
gliamo operare, passiamo a caricare il file sor-
Qualità documentazione  gente che ci interessa; questo può essere fatto
Magari l’help in linea lascerà un po’ delusi (anche se molto conci-
so illustra tutte le funzionalità del programma) ma sul sito di rife- attraverso il pulsante relativo oppure con un
rimento si possono trovare tutte le informazioni necessarie. comodissimo drag&drop in puro stile Windows.
A questo punto il documento viene presentato
nell’area di testo più in alto. Per “colorizzare”
CodeColorizer il nostro sorgente è sufficiente cliccare l’omoni-
di Angelo Ossola mo pulsante; il relativo risultato viene presen-
CodeColorizer, ovvero quando la semplicità è tato, in formato HTML nell’area di testo più in
tutto; vi è mai capitato di dover
realizzare una pagina HTML (da
distribuire in internet o nel vo-
stro gruppo di lavoro) che pre-
senti codice sorgente con lo stes-
so appeal grafico che siete abi-
tuati a vedere nell’ambiente di
sviluppo che usate per realizza-
re le vostre applicazioni? Se si,
e se, magari, avete anche perso
diverse decine di minuti per im-
paginare il vostro codice con le
tabulazioni ed i colori adeguati
a far apparire il tutto il più pos-
sibile simile alla struttura pre-
sentata ad esempio da Visual
Studio .NET, allora CodeColo-
rizer è il tool che avreste potu-

N. 65 - Settembre/Ottobre 2005 VBJ 53


.NET TOOLS

basso. La presenza di queste due aree di testo è SharpWebMail


veramente comoda per apportare modifiche in di Raffaele Di Natale
corsa al codice sorgente per poi vederle imme- Nel panorama delle WebMail application, ricco
diatamente applicate al codice sviluppato dal nelle soluzioni e nelle tecnologie adottate, Shar-
programma (sempre dopo essere passati per il pWebMail si distingue principalmente per la sem-
tasto “colorize”). plicità dell’installazione e della configurazione. Il
Un’altra comodità offerta dal software è la pos- progetto che sta alle sue spalle è sicuramente de-
sibilità di visualizzare un’anteprima del risulta- gno di nota, poiché l’autore ha utilizzato tre mo-
to ottenuto all’interno di una finestra del nostro duli software, sempre open source, tutti leader
browser predefinito. Volendo salvare, infine, il nel proprio ambito. Un’interfaccia senza fronzoli
nostro lavoro abbiamo la possibilità di farlo sia e funzionalità base efficienti consentono un fa-
in formato HTML che in formato RTF. cile adattamento alle più comuni configurazioni
Un unico appunto che potrebbe essere mosso dei servizi di posta elettronica. Le pagine .ASPX
all’autore del tool è l’impossibilità di modifica- sviluppate in C# richiamano cinque moduli, dei
re l’output prodotto per poter, ad esempio, por- quali i primi tre sono legati direttamente all’ap-
tare piccoli adattamenti al codice ottenuto sen- plicazione ed i restanti sono di supporto:
za doversi affidare ad altri strumenti. Se la se-
conda area di testo diventasse un editor HTML,  SharpWebMail.dll, il modulo principale;
anche semplice, il lavoro sarebbe ulteriormen-  SharpMimeTools.dll, modulo in versione beta
te semplificato. per il parsing dei messaggi MIME;
E verrebbe in grande aiuto qualora si avesse  SharpWebMail.resources.dll, per le risorse mul-
la necessità di inserire in una pagina di un sito tilingua;
del codice che possa, però, mantenere la format-  Log4tNet.dll, modulo per i servizi di login;
tazione originale.  OpenSmtp.dll, modulo per i servizi SMTP;
Sul sito del programma, oltre ad altri tool mol-  FredCK.FCKeditorV2.dll, modulo dell’html edi-
to interessanti per gli sviluppatori, è possibile tor più conosciuto.
anche registrarsi ad una mailing list che per-
mette di restare sempre informati su eventua- L’applicazione si basa sul .Net Framework 1.1
li aggiornamenti. di Microsoft e su Mono 1.0, ma all’interno della
directory bin sono presenti i binari per il .Net
Prodotto Framework 2.0 e per e Mono 2.0. Pertanto que-
CarlosAg.CodeColorizer sta web application può girare indistintamente
sia su Windows sia sugli altri sistemi suppor-
Url di riferimento
http://www.carlosag.net/ tati da Mono. Per quanto concerne il web può
essere utilizzato con gli IIS (Internet Informa-
Stato Release
v1.0.0.1 tion Services) oppure con Apache, ovviamente
insieme a Mono se non si tratta di un sistema
Semplicità d’uso 
L’uso di questo tool risulta già dal primo approccio decisamen- Windows.
te banale. È necessario predisporre l’indirizzo di almeno
Utilità  un server POP3 (o IMAP) e di un server SMTP.
Permette di realizzare un’operazione, probabilmente tediosa, in SharpWebMail è stato testato con i browser
un attimo. internet più diffusi al momento e vale a dire
Qualità prodotto  Internet Explorer 6.0 e FireFox 1.0. L’applica-
Realizza un’unica funzionalità ma in modo egregio: massimo risul- zione descritta in quest’articolo è stata instal-
tato con il minimo sforzo.
lata su Windows XP SP2 con gli IIS. SharpWeb-
Qualità documentazione  Mail, in versione 0.11 beta, può essere scarica-
Considerato l’evidente facilità d’uso non si può certo chiede-
to gratuitamente: il pacchetto comprende sia i
re di più.
file sorgente che i binari. Dopo aver scaricato il

54 VBJ N. 65 - Settembre/Ottobre 2005


.NET TOOLS

/>
</servers>

<servers>
<server
name=”Default SMTP Server”
regexp=”*”
protocol=”smtp”
host=”smtp.dominio.it”
port=”25”
/>
</servers>

Come si evince dai tag è possibile in-


serire anche più di un server SMTP e
POP3/IMAP. I commenti presenti all’in-
terno di questo file aiutano a capire il
significato di questi ed altri campi del-
le varie sezioni. Non resta che salvare il
file modificato e lanciare l’applicazione:
file ZIP ed averne estratto il contenuto, si può l’indirizzo http://localhost/webmail/ pun-
procedere all’installazione. Come accennato in terà direttamente alla pagina login.aspx che mo-
precedenza questa fase è semplicissima ed è strerà il form di login.
descritta all’interno del file readme.txt presen- Il titolo della finestra della pagina web può esse-
te nella directory doc. Il contenuto della cartel- re personalizzato tramite il campo title della sezio-
la asp.net deve essere spostato all’interno della ne general cosi come il titolo del form di login me-
cartella di destinazione del server web, configu- diante title della sezione login e la lingua di default
rando in esso la directory Webmail. mediante il campo default_lang.
A questo punto non resta che personalizzare Relativamente al campo username le possibili-
l’applicazione in base ai servizi che ci sono mes- tà sono tre:
si a disposizione, alla modalità d’accesso pre-
ferita e alla tipologia della rubrica prescelta.  Richiedere l’indirizzo completo, per esempio
SharpWebMail è una web application ASP.NET raffaele@dominio.it, fissando mode=‘1’;
e pertanto la configurazione avviene mediante  Richiedere semplicemente il nome, per esem-
il consueto file web.config che si trova sempre pio raffaele, con mode=‘2’;
all’interno della cartella WebMail. Per una con-  Accodare al nome inserito un’ulteriore stringa
figurazione minima basta intervenire sulle due standard per tutti gli utenti, mediante il campo
sezioni principali read e send, che si riferisco- append. Per esempio se append=“@dominio.it”
no rispettivamente alle impostazioni dei server e lo username è raffaele allora la stringa finale
della posta in entrata e in uscita. Di seguito si sarà raffaele@dominio.it. In questo caso sarà
propone un esempio per read e per send, da però necessario definire il campo mode=‘3’.
adattare alle proprie esigenze:
Un’applicazione di posta elettronica che si ri-
<servers> spetti non può far mancare la rubrica ai propri
<server
utenti: gli indirizzi potrebbero essere collocati in
name=”Default POP3 Server”
un file .MDB di Access o più semplicemente ge-
regexp=”*”
protocol=”pop3” stiti da un servizio LDAP/Active Directory.
host=”pop3.dominio.it” Supponiamo di aver predisposto un database
port=”110” denominato rubrica.mdb, all’interno del quale

N. 65 - Settembre/Ottobre 2005 VBJ 55


.NET TOOLS

abbiamo definito una tabella denominata Ta- È possibile inserire anche più di una rubrica.
ble1 formata da due colonne nome ed email ri- L’applicazione può filtrare i messaggi ricevuti,
spettivamente. eliminando dal contenuto degli stessi sia codi-
Salviamo il file in C:\ e inseriamo una sezione ce html superfluo sia script potenzialmente pe-
<addressbook> nel file web.config. A seconda ricolosi. Per far questo poniamo il campo sani-
della tipologia della rubrica prescelta potrebbe tizer_mode= ‘1’ nella sezione message. Questa
essere necessario impostare la corrispondente funzionalità non è ancora del tutto affidabile. Da
sorgente dati ODBC. notare infine la sezione authentication che con-
sente di scegliere tra quattro modalità differen-
<addressbook ti per il login: tramite il form standard dell’ap-
Name=”MS Access Address Book”
plicazione, il form di Windows, quello passport
Type=”odbc”
oppure non definirne alcuno.
ConnectionString=”Driver={Microsoft Access Driver(*.mdb)};DBQ=C:
\rubrica.mdb” SharpWebMail si presenta con un’interfaccia
SearchString=”SELECT nome, email FROM Table1” ormai standard per questo tipo di applicazioni.
NameColumn=”nome” Sulla parte alta sono presenti i pulsanti di navi-
EmailColumn=”email” gazione, di logout e d’aggiornamento; a sinistra
PageSize=”10”
si trovano i comandi principali e sulla parte de-
SearchStringRealName=”SELECT nome, email FROM Tabella1 WHERE
email=’$USERNAME$’”
stra il form relativo al messaggio in uscita.
/> Nella parte bassa è visibile la finestra della ru-
brica. Intervenendo sul file Sharpwebmail.css è

56 VBJ N. 65 - Settembre/Ottobre 2005


.NET TOOLS

possibile definire stili differenti per l’applicazio- Come si può quindi dedurre, la scrittura di test
ne. Da quanto emerso appare evidente che si trat- per progetti particolarmente complessi può esse-
ta di un programma semplice e ben congegnato. re un’operazione particolarmente lunga e labo-
Un aspetto migliorabile, anche se secondario, è il riosa. Per semplificare la creazione e la gestio-
numero delle funzionalità a disposizione. ne dei test, esistono i cosiddetti “Unit Testing
framework”, che aiutano a scrivere codice, ad
Zanebug effettuare il debug del codice e ad integrare nel
Lo Unit Testing visuale miglior modo possibile i test all’interno del co-
di Fabio Perrone dice. Uno dei migliori “Unit Testing framework”
Per “Unit Testing” s’intende l’effettuazione di per Microsoft .NET è senza dubbio NUnit [1],
verifiche funzionali e d’affidabilità riguardan- che permette di segnare il codice con attribu-
ti il comportamento di determinati componenti ti per indicare quali metodi devono essere ese-
rispetto al soddisfacimento di requisiti defini- guiti quando un test ha successo.
ti in fase di progettazione. Nello sviluppo di un Per chi avesse già utilizzato altri framework,
progetto software, lo Unit Testing sta assumen- la seguente nomenclatura potrebbe essere fami-
do un ruolo sempre più preponderante, senza liare, anche se è bene avere sempre chiare in
dubbio anche perché rappresenta una “pietra mente le definizioni di Test, che è un metodo
miliare” dell’Extreme Programming o XP. Gli che esegue delle convalide interne e può avere
unit test sono scritti all’interno del codice che esito positivo o negativo; TestFixture, che è una
deve essere testato. classe che contiene più metodi di test; TestAs-

N. 65 - Settembre/Ottobre 2005 VBJ 57


.NET TOOLS

sembly, che è una collezione di TestFixture in che permette di eseguire o interrompere i test,
un assembly; TestSuite, che è una collezione di mostrare la percentuale d’elaborazione dei test
TestAssembly costruita dinamicamente da Za- correnti e, a test ultimato, individuare grafica-
nebug per ogni assembly che viene caricato al- mente la percentuale di test che hanno avuto
l’interno del programma. Prima di analizzare le successo, il tutto evidenziato dalla colorazione
notevoli possibilità offerte dalla parte grafica di differente in base all’esito dei test: ovviamente
Zanebug, vediamo come scrivere test all’inter- rosso se uno o più test non ha avuto esito posi-
no del codice che possano poi essere elaborati tivo, verde altrimenti.
ed analizzati dal nostro software. Il TreeView presente nella schermata princi-
Il primo passo consiste nel mettere un riferi- pale elenca la struttura ad albero dei Test, Te-
mento alla dll che costituisce il motore di Za- stFixture, TestAssembly e TestSuite, permet-
nebug: Adapdev.UnitTest.dll, quindi importia- tendo di selezionare o meno un test per la sua
mo il namespace Adapdev.UnitTest all’interno eventuale esecuzione. Selezionando una qual-
del nostro codice; così facendo siamo in grado siasi voce del TreeView vengono evidenziate tut-
di utilizzare tutti gli attributi messi a disposi- te le caratteristiche del test che si possono im-
zione da Zanebug per identificare una classe mettere in fase di scrittura all’interno del co-
come classe di test (attributo TestFixture) e un dice, già menzionate in precedenza (categoria,
metodo come metodo di test (attributo Test). descrizione, ecc.).
Portando a termine questi semplici passi, ab- D’assoluto interesse sono i numerosi Tab pre-
biamo già creato la base per l’effettuazione di senti nell’interfaccia principale che permetto-
qualsiasi unit test a cui vogliamo sottoporre il no di filtrare in numerosi modi i test: tutti, solo
nostro codice. quelli che hanno avuto esito positivo, solo quel-
Quando si esegue il testing “a mano” senza li negativi oppure quelli ignorati.
usare alcun framework, assumono una notevo- Per ognuno di questi tab vengono illustrati
le importanza le asserzioni, caratteristica che si una notevole mole di dati, quali il tipo di test,
riflette in maniera più avanzata anche in Zane- il messaggio di un’eventuale eccezione genera-
bug tramite la classe Assert, che prevede meto- ta, il tempo medio d’esecuzione del test, la du-
di per controllare se due oggetti sono uguali, se rata in percentuale del test rispetto al TestSui-
due oggetti hanno lo stesso riferimento (in poche te, la quantità di memoria consumata dal test,
parole se puntano allo stesso oggetto), se una il numero d’iterazioni del test.
determinata condizione è falsa e altre interes- Oltre a queste caratteristiche, il menu conte-
santi opzioni ben documentate nella guida. stuale d’ogni tab prevede ulteriori interessanti
Oltre a questi fondamentali attributi che forni- analisi grafiche, come il confronto tra più test
scono l’ossatura per approntare un buon test, è o la media di un test evidenziato rispetto alla
possibile inserire una descrizione per ogni test media totale. Oltre a tutto ciò, il tab “Perfmon”,
che si compie, la categoria che si vuole fare ap- come suggerisce il nome, offre un Performance
partenere un determinato test, se da un deter- Monitor per tener traccia di statistiche presta-
minato metodo ci si aspetta una ben specifi- zionali senza dover lasciare l’ambiente di Za-
ca eccezione, oppure se un metodo deve essere nebug ricorrendo magari ad altri strumenti o al
ignorato in fase d’esecuzione. Performance Monitor nativo di Windows.
Dopo aver brevemente esaminato le istruzioni Due ulteriori caratteristiche rendono il pro-
che devono essere inserite nel codice per poter dotto completo sotto ogni punto di vista: la
effettuare i test, passiamo ora all’analisi dell’in- console di Zanebug e l’integrazione con Visual
terfaccia utente di Zanebug, che senza dubbio Studio.NET.
rappresenta l’aspetto più interessante e più po- La prima permette l’esecuzione dei test da riga
tente di tutto il tool. di comando con una gamma di scelte molto am-
La parte principale dell’interfaccia utente del pia, simile a quella della parte grafica (escluse
programma è occupata dalla cosiddetta Test Bar, le statistiche avanzate e i grafici, ovviamente),

58 VBJ N. 65 - Settembre/Ottobre 2005


.NET TOOLS

permettendo così di utilizzare la modalità batch;


la seconda installa un add-in nell’IDE di Visual Prodotto
Zanebug
Studio.NET (solo versione 2003, per ora), che in-
serisce una voce al menu di contesto utile per Url di riferimento
http://www.adapdev.com
aggiungere in modo rapido gli attributi necessa-
ri in quel punto attivo del codice sorgente, non- Stato Release
Stabile (versione corrente 1.5.0.1)
ché una Toolbar per poter eseguire i test diret-
tamente all’interno di Visual Studio.Net. Semplicità d’uso 
La semplice ma funzionale interfaccia grafica facilita molto.
La versione attuale, la 1.5.0.1, scaricabile gra-
tuitamente, fornisce, come si è potuto dedurre, Utilità 
Per chi utilizza lo Unit Testing è uno strumento fondamentale per
buone funzionalità per l’automazione dei test,
semplificare la creazione e l’utilizzo di test visuali.
oltre ad una dettagliata analisi dei risultati con-
seguiti. Oltre ad essere completamente gratui-
Qualità prodotto 
Affidabile, nei test sul prodotto eseguiti non ha mai mostrato par-
to, è anche possibile effettuare il download del ticolari problemi.
codice sorgente, caratteristica che per i più vo-
Qualità documentazione 
lenterosi rende ancora più appetibile quest’ot- Presenti sia help on line che documentazione su Web.
timo strumento.

N. 65 - Settembre/Ottobre 2005 VBJ 59


SOFTWARE ENGINEERING

I design pattern
più famosi implementati
in VB.NET
Quarta puntata

Il pattern Adapter suggerisce come modificare una classe


server in modo da adattarsi all’interfaccia richiesta da
altre classi client

DP 4
di Lorenzo Vandoni

• Motivation. A volte può capi-

I
pattern descritti nel libro “Design Pattern” di
Gamma, Helm, Johnson e Vlissides sono or- tare che un’applicazione che
ganizzati in tre categorie: pattern di creazio- si sta sviluppando richieda da
ne, di comportamento e strutturali. parte di alcune classi un’in-
Nelle due puntate precedenti abbiamo esaminato terfaccia ben precisa. Questo
due tra i più noti pattern di comportamento, Itera- capita soprattutto durante le
tor e Observer, e un pattern di creazione, Factory operazioni di manutenzione,
Method. Concludiamo questa piccola serie mostran- quando cioè un’applicazione
do un pattern strutturale, Adapter. viene modificata per rispon-
dere a nuove esigenze.
Il pattern Adapter, descrizione Per esempio, potrebbe capita-
Come al solito, la descrizione del pattern verrà re che le funzionalità di log di
suddivisa in tre sezioni. un programma, inizialmente
In questa prima sezione ne verranno discussi sco- dirette verso un normale file
po, motivazioni e applicabilità. di testo, debbano in un secon-
do tempo essere convertite in
• Intent. Lo scopo del pattern è quello di per- modo da memorizzare le righe
mettere ad una classe A di utilizzare i servizi di log in una tabella di databa-
di una classe B, nell’ipotesi che B implementi se. In questi casi, si può veri-
le funzionalità desiderate, ma fornisca un’in- ficare la necessità di sfruttare
terfaccia pubblica incompatibile con quella ri- delle classi di libreria che of-
chiesta da B. frono le funzionalità deside-
rate, ma tramite un’interfac-
cia di programmazione diver-
sa da quella richiesta dall’ap-
Lorenzo Vandoni è laureato in Informatica, ed è uno spe- plicazione. Le alternative sono
cialista di progettazione e sviluppo con tecniche e linguaggi
object-oriented. Ha collaborato alla realizzazione di framework,
tre: o si modificano le classi di
strumenti di sviluppo e software commerciali in C++, Java e libreria, o si modifica il codice
Visual Basic. Può essere contattato tramite e-mail all’indirizzo dell’applicazione, o si crea un
vandoni@infomedia.it. adattatore che funga da trami-

60 VBJ N. 65 - Settembre/Ottobre 2005


SOFTWARE ENGINEERING

te. Il pattern Adapter suggerisce appunto la teServer, sfruttando però un’interfac-


creazione di un adattatore. cia diversa. Il fatto che il programma
client sia rappresentato tramite una sola
• Applicabilità. Il pattern è applicabile ogni classe è ovviamente una semplificazio-
volta in cui sia impossibile o non conve- ne, che però non modifica la struttura
niente modificare sia il codice client sia della soluzione.
il codice server, e sia necessario accedere
alle funzionalità di una classe utilizzando ServerInterface rappresenta l’interfac-
°
un’interfaccia di programmazione diversa cia che l’applicazione client intende uti-
da quella fornita dal codice server. lizzare. A seconda dei casi, si potrà trat-
tare di una vera interfaccia, di una clas-
se base, oppure di un insieme di classi
A volte può capitare che ed interfacce. In pratica, ServerInter-
face rappresenta l’insieme di funzioni
un’applicazione richieda utilizzate dalla classe Client.
da parte di alcune classi
ConcreteServer identifica la classe, che
un’interfaccia ben precisa °
si suppone già presente e implementa-
ta all’interno di un’altra applicazione, di
un toolkit o di una libreria, che forni-
Soluzione del problema sce le funzionalità desiderate, ma che si
Per questo problema il pattern suggeri- rende accessibile tramite un’interfaccia
sce due diverse soluzioni. La prima utilizza di programmazione (cioè un insieme di
l’ereditarietà, la seconda l’incapsulamento. La proprietà e funzioni) diversa e non com-
struttura delle classi, nei due casi, è mostrata patibile da ServerInterface.
nelle Figure 1 e 2. Adapter è la classe che fornisce il lega-
°
me tra Client e ConcreteServer. Questa
• Structure. Le due figure sono molto simi- classe implementa l’interfaccia Serve-
li. L’unica differenza è data dalla relazione rInterface, ovvero presenta l’insieme di
tra le classi Adapter e ConcreteServer. Nel proprietà e funzioni che il programma
primo caso abbiamo una relazione di ere- client si aspetta di usare, e ne delega
ditarietà, mentre nel secondo caso l’Adap- l’esecuzione al ConcreteServer.
ter incapsula il ConcreteServer per forni- Sono due i modi con cui questa delega
re le funzionalità imple-
mentate da quest’ultimo
tramite l’interfaccia Ser-
verInterface.

• Participants. Vediamo più


in dettaglio le responsabi-
lità delle varie classi ed in-
terfacce:

La classe Client rap-


°
presenta l’applicazio-
ne client, che ha la Figura 1 Una possibile soluzione del pattern Adapter
necessità di sfruttare
i servizi del Concre-

N. 65 - Settembre/Ottobre 2005 VBJ 61


SOFTWARE ENGINEERING

può essere implemen-


tata, rappresentati ri-
spettivamente dalle
Figure 1 e 2.
Nel primo caso viene
utilizzata l’ereditarietà
di implementazione,
mentre nel secondo
caso la delega avviene
in modo esplicito tra-
mite incapsulamento.
Figura 2 Una soluzione alternativa per il pattern Adapter
La prima tecnica è ap-
plicabile solo in C++,
unico linguaggio che
fornisce la possibilità di ereditare il com- turazione di vecchie applicazioni per in-
portamento di una classe senza ereditar- corporare nuove funzionalità. Esempi noti
ne l’interfaccia, nonché unico linguaggio di applicazione di Adapter possono esse-
che supporta l’ereditarietà multipla (ne- re considerati i due assembly che consen-
cessaria nel caso in cui ServerInterface tono di sfruttare all’interno di applicazio-
sia una classe base). Per questo motivo, ni .NET i vecchi provider OLEDB e i vec-
nell’implementazione di esempio verrà chissimi driver ODBC.
utilizzata la seconda tecnica. Questi assembly implementano un’inter-
faccia ben specifica, costituita dalle varie
• Collaborations. La struttura dinamica di interfacce definite in System.Data, come
questo pattern non ha nulla di particolare. IDBConnection e IDBCommand, ma de-
La classe Client istanzia un Adapter trami- legano l’esecuzione delle varie funzioni ai
te l’interfaccia ServerInterface. L’Adapter, a provider e ai driver sottostanti.
sua volta, crea un istanza di ConcreteSer-
ver. Tutte le successive chiamate da parte Implementazione del pattern
di Client a metodi implementati dall’Adap- in VB.NET
ter verranno da questo convertiti in chiama- Come esempio di implementazione conside-
te al ConcreteServer. riamo un’applicazione VB.NET al cui interno
sia stato implementato un meccanismo di log
Conseguenze e benefici “artigianale”, e supponiamo che si voglia so-
Vediamo ora quali siano i punti di forza del stituire in un secondo tempo questo mecca-
pattern ed alcune applicazioni pratiche: nismo con qualcosa di più evoluto, costituito
nell’esempio dall’utilizzo della classe Trace
• Consequences. La conseguenza principale del namespace System.Diagnostics.
derivante dall’utilizzo di Adapter risiede nel L’esempio è costituito da una form, nel cui
fatto che esso permette di non modificare né evento Form_Load è stato introdotto un er-
l’applicazione client, né il codice del server, rore. L’errore viene gestito all’interno di un
normalmente incluso in una libreria, con- blocco Try Catch con una chiamata al meto-
sentendo però all’applicazione di sfruttare do Trace dell’interfaccia GenericLogger. L’im-
le funzionalità di quest’ultimo. plementazione “artigianale” prevede che il
GenericLogger sia implementato da una clas-
• Known uses. La maggior parte dei casi pra- se DummyLogger, che si limita a visualiz-
tici in cui questo pattern si rende utile na- zare il messaggio di trace all’interno di un
scono nel contesto di operazioni di ristrut- message box. Il pattern Adapter è costituito

62 VBJ N. 65 - Settembre/Ottobre 2005


SOFTWARE ENGINEERING

dalla classe LoggerAdapter, che implementa Listeners.Add. Nell’esempio come listener vie-
l’interfaccia GenericLogger in modo differen- ne utilizzata un’istanza della classe TextWri-
te, delegando l’esecuzione del log alla classe terTraceListener, che scrive il messaggio di
System.Diagnostic.Trace. trace sulla console.

Conclusioni
Adapter è un pattern che risulta utile soprat-
Il pattern è applicabile ogni tutto durante la manutenzione o la ristruttu-
volta in cui sia impossibile razione di applicazioni e librerie, in quanto
modificare il codice client e consente di sfruttare nuove funzionalità sen-
za modificare in modo sensibile il codice ori-
il codice server ginale dell’applicazione.
Perché il pattern possa essere sfruttato, però,
è necessario che l’applicazione sia stata ori-
Questa classe del framework implementa le ginariamente progettata in modo corretto ed
funzioni di trace informando dei listener che estendibile, incapsulando bene i vari moduli
si possono registrare richiamando il metodo e le loro interfacce.

N. 65 - Settembre/Ottobre 2005 VBJ 63


I N O F F E R TA V B J 6 5
Scrivi a
Web Services Programming Windows
Platform Architecture book@infomedia.it Presentation Foundation
AA. VV. specificando di C. Sells - I. Griffiths

nell’oggetto della
Prentice Hall
e-mail: O’ Reilly
ISBN 0131488740
456 pp - 46,95 €
IN OFFERTA ISBN 0596101139
447 pp - 39,95 €
VBJ n. 65
OPPURE
inviaci il coupon
Microsoft SQL Server 2005. Head First
Changing the Paradigm sottostante Design Patterns
al numero di fax di Eric Freeman et al.

0587/732232
Sams Potrai acquistare O’Reilly
ISBN 0672327783 ISBN 0596007124
504 pp - 34,70 €
i libri qui riportati con 688 pp - 44,95 €
uno
SCONTO
Java and SOAP
ECCEZIONALE Starting Out
di R. Englander with Visual Basic.Net
del 10% anche se di T. Gaddis et al.
acquisti solo un
libro
O’Reilly Addison Wesley
ISBN 0596001754 OPPURE ISBN 1576760944
276 pp - 41,40 € 890 pp - 62,70 €
del 20% se acquisti
3 libri

VBJ 65
LIBRI
Real World SQL Build Your Own .NET
Administration with Perl Language and Compiler
Autore Linchi Shea Autore Edward G. Nilges
Editore Apress Editore Apress
ISBN 159059097X ISBN 1590901348
Lingua Inglese Lingua Inglese
Anno 2003 Anno 2004
Pagine 798 Pagine 388
Prezzo € 64,15 Prezzo € 50,50

T O
rovare in un titolo di libro le parole “SQL Server” e “Perl” può biettivo di questo libro è guidare il lettore attraverso la progetta-
suscitare qualche perplessità. In effetti, uno dei punti di forza zione e l’implementazione di un compilatore per un linguaggio
di questo libro consiste proprio nel mostrare a chi usa un compatibile con lo storico QuickBasic, interamente realizzato
ambiente Microsoft che possono esserci dei casi in cui può valere in Visual Basic .NET e in grado di produrre codice assembly per la
la pena di usare altri prodotti, come appunto Perl, per semplificare piattaforma .NET. Dopo un piacevole excursus storico sui compilatori
i compiti di amministrazione. Si può anche aggiungere che il fatto e, più in particolare, del linguaggio BASIC, il testo presenta una breve
stesso di rendere nota l’esistenza di Activestate Perl è un bonus introduzione al freamework .NET. Non si tratta della solita presentazione
di per sé! dell’ambiente, ma di una analisi ragionata dei componenti fondamentali
Purtroppo questo pregio diventa anche la maggiore limitazione del (CTS, CLS e CLR) con l’obiettivo di scrivere un compilatore per esso.
libro. Chi è un esperto amministratore di SQL Server ma non conosce L’autore illustra i concetti base della teoria dei compilatori e una analisi
nulla di Perl viene guidato passo passo alla comprensione di concetti sintattica del linguaggio QuickBasic, cui segue lo sviluppo dei primi
astrusi quali le pattern e le espressioni regolari, o a leggere un file componenti del quickBasicEngine vero e proprio. Dopo aver disegnato
di configurazione; viceversa, chi proviene da un ambiente Unix e la modellazione ad oggetti del linguaggio in uso, vengono discussi nel
sperasse di comprendere meglio il funzionamento pratico di SQL dettaglio il modulo parser e il generatore di codice. Il lettore è guidato
Server si trova a disagio, quasi come fosse capitato in un mondo attentamente sia sugli aspetti teorici (espressioni regolari, BNF…) che in
alla rovescia. Gli algoritmi e le procedure presentati nel libro sono quelli pratici (ottimizzazione del codice). Tutto il sorgente dell’ambiente
inoltre molto specializzati, e quindi non particolarmente utili per chi presentato nel libro è disponibile online (evitando, dunque, di appesan-
volesse usare ad esempio MySQL come database; insomma non tire inutilmente il volume); al fine di avere una lettura proficua del testo,
lo si può definire certo un libro per tutte le stagioni. è consigliabile avere il codice a disposizione sul proprio PC e seguire
Occorre però riconoscere che se si fa parte del target cui il libro dettagliatamente i passi indicati dall’autore. Lo studio del compilatore
è dedicato, il suo valore si nota subito. Infatti i vari problemi scelti prosegue con una breve analisi del funzionamento di assembler e
sono indubbiamente quelli che possono capitare nella vita di chi interpreti e delle implicazioni nello sviluppo dell’applicazione. Prima
gestisce basi di dati; inoltre la spiegazione di contorno alla solu- di concludere, l’autore si sofferma su alcune problematiche legate
zione è sempre molto dettagliata, e cerca di spiegare anche cosa alla scelta del linguaggio che si intende supportare. Il tema trattato è
ci sta sotto, senza limitarsi a porgere la risposta. Risulta più facile estremamente particolare, destinato a un pubblico specialistico. Se
quindi adattare gli esempi al proprio caso particolare. Fortunata- ne sconsiglia una lettura “casuale”, distratta o saltuaria! Gli studenti
mente presso il sito dell’editore è possibile scaricare una versione potranno trovarci spunti interessanti per comprendere il funzionamento
elettronica di tutti gli esempi, a partire da http://www.apress.com/ dei compilatori o cimentarsi nella progettazione di un linguaggio.
book/bookDisplay.html?bID=171.
In definitiva, un libro per una fascia selezionata di lettori che però
lo troveranno di grande utilità. Pro
È un testo “coraggioso”, perché affronta un tema fondamentale (teoria
e pratica dei compilatori) rendendolo attuale attraverso l’implementazio-
ne all’interno del Framework .NET. Ottimo come base di partenza per
progetti più complessi (eventualmente per supportare altri linguaggi),
Pro sicuramente consigliato come testo didattico di riferimento.
Le spiegazioni sono non solo dettagliate, ma danno anche un’idea
di cosa c’è dietro alla soluzione proposta. Contro
La scelta di VB.NET per l’implementazione del compilatore è discu-
Contro tibile; probabilmente sarebbe stato più interessante vederne una in
Il libro è davvero utile solo per chi deve amministrare sistemi C# (a questo proposito l’autore sottolinea che tutti i programmatori
SQL Server. C# conoscono VB.NET, ma non è vero il viceversa...).

Maurizio Codogno Stefano Sanna

N. 65 - Settembre/Ottobre 2005 VBJ 65