Top Banner
68

v2005 05 vbj65

Jun 07, 2015

Download

Documents

turing-club
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: v2005 05 vbj65
Page 2: v2005 05 vbj65
Page 3: v2005 05 vbj65
Page 4: v2005 05 vbj65

E D I T O R I A L E

N. 65 - Settembre/Ottobre 2005 VBJ4

Come 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-dando Visual Basic e C#. Così mi sono tenuto un pomeriggio da parte per dare un’occhiata agli articoli già disponibili.

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.

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 Linq, una specie di embedded SQL che permette di immergere query SQL direttamente nel codice. In teoria, Linq dovrebbe promuovere una più stretta integrazione tra i database relazionali e i modelli ad oggetti (intrinsecamente gerarchici) costruiti nella propria appli-cazione. In pratica, però, questa integrazione non si può affatto dare per scontata. Alcuni progetti simili – primo tra tutti, ObjectSpaces – sono falliti oppure comunque non hanno mai conquistato il cuore degli sviluppatori, che continuano a produrre ottime applicazioni gestionali senza bisogno di queste infrastrutture (o sovrastrutture, se preferite). L’altro punto importante è che se Linq non offrirà prestazioni identiche a quelle offerte da SQL tradizionale, nessuno vorrai mai utilizzarlo.

Il problema, comunque, non è tanto quello di aggiungere feature che poi nessuno userà 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 As, lasciando al compilatore il compito di determinare il tipo necessario. Con tanti saluti alla leggibilità del codice!

Il discorso è complesso e non è certo adatto alla paginetta che questo editoriale mi concede. La stessa Microsoft ha dichiarato che questa pre-release serve soprattutto a raccogliere le impressioni della comunità degli sviluppatori. Ho scritto qualcosa sul mio blog e sicuramente tornerò sull’argomento man mano che altre novità diventeranno disponibili, e sarà interessante confrontare le opinioni di tutti coloro che usano questi strumenti “sul campo”.

Francesco [email protected]

www.dotnet2themax.it/blog

Il futurodei linguaggi .NET

o n l i n e . i n f o m e d i a . i tn. 65 - settembre/ottobre 2005bimestrale - anno undicesimo

Direttore Re spon sa bi leMarialetizia Mari ([email protected])

Direttore EsecutivoFran ce sco Balena ([email protected])

Managing EditorRenzo Boni ([email protected])

CollaboratoriMaurizio Codogno

Stefano Corti Emanuele DelBono Raffaele Di Natale

Fabio Fabozzi Claudio Maccari Angelo Ossola Fabio PerronePaolo Pialorsi

Francesco Quaratino Stefano Sanna

Lorenzo Vandoni

Direzione Natale Fino ([email protected])

Marketing & Advertising Segreteria: 0587/736460

[email protected]

AmministrazioneSara Mattei

([email protected])

GraficaManola Greco ([email protected])

Technical BookLisa Vanni ([email protected])

Segreteria Enrica Nassi

([email protected])

StampaTIPOLITOGRAFIA PETRUZZI

Citta’ di Castello (PG)

Ufficio AbbonamentiTel. 0587/736460 - Fax 0587/732232e-mail: [email protected]

www.infomedia.it

Gruppo Editoriale Infomedia srlVia Valdera P., 116 - 56038 Ponsacco (PI) Italia

Tel. 0587/736460 - Fax 0587/[email protected]

Sito Web www.infomedia.it

Manoscritti e foto originali anche se non pub bli ca ti, non si restituiscono. È vietata la ri pro du zio ne

anche parziale di te sti e immagini.

Si prega di inviare i comunicati stampa e gli inviti stampa per

la redazione all’indirizzo: [email protected]

Visual Basic Journal è una rivista diGruppo Editoriale Infomedia S.r.l. Via Valdera P, 116 Ponsacco - Pisa.

Registrazione presso il Tribunale di Pisa n. 20/1999

Page 5: v2005 05 vbj65
Page 6: v2005 05 vbj65

6

SOMMARIO

VBJ N. 65 - Settembre/Ottobre 2005

N.65S E T T EM B R E / OT TO B R E

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

a cura di DevLeap

SPECIALE

20Controlli multimediali in Visual Basic 6Non 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

Controllo Remoto in Visual Basic .NET (seconda puntata)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

Supporto XML in SQL Server 2005Sql 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

MULTIMEDIA

APPLICAZIONI

26

DATABASE

33

Page 7: v2005 05 vbj65

7N. 65 - Settembre/Ottobre 2005 VBJ

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.

Codice allegato

Editoriale 4

.NET Tools 52

Libri 65

RUBRICHE

Sviluppare Servizi Windows con .NETIn 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 WSEVediamo le principali caratteristiche di Microsoft Web Services Enhancements dal punto di vista del SOAP Messaging.

di Paolo Pialorsi

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.

di Lorenzo Vandoni

.NET

38

45

SOFTWARE ENGINEERING

60

Page 8: v2005 05 vbj65

8 VBJ N. 65 - Settembre/Ottobre 2005

Dall’11 al 16 settembre 2005 si è tenuta a Los Angeles la Professional Developer Conferen-ce 2005 (PDC05). Si tratta di un evento tec-

nico organizzato da Microsoft Corporation e rivolto a programmatori che utilizzano le tecnologie di Re-dmond per lo sviluppo delle proprie applicazioni. È un evento che non ha una cadenza fissa, ma che vie-ne organizzato solo quando Microsoft ha qualcosa di particolarmente interessante da annunciare agli svi-luppatori. Quest’anno gli argomenti di maggior rilievo sono stati l’imminente rilascio del .NET Framework 2.0, accompagnato da SQL Server 2005 e BizTalk Ser-ver 2006, ma anche e soprattutto l’annuncio di nuove tecnologie e prodotti che vedranno la luce nei prossi-mi due anni. Tra questi possiamo sicuramente citare WinFX, che rappresenta il framework di base per le applicazioni business dei prossimi anni. A oggi Win-FX è rappresentato dall’insieme di Windows Presen-tation Foundation (WPF, conosciuto con il nome in co-dice “Avalon”) per la gestione dell’interfaccia utente, Windows Communication Foundation (WCF, nome in codice “Indigo”) per lo strato di comunicazione e ser-vizi SOAP e Windows Workflow Foundation (WWF, sconosciuto ai più sino a PDC05) per la gestione dei processi e flussi aziendali. Un altro argomento che ha avuto il suo peso è l’anteprima della prossima versio-ne di Microsoft Office, ormai giunto alla versione 12, e di Windows SharePoint Services 3.0.

Grande rilievo hanno avuto an-che la versione 3.0 del linguaggio C# e la tecnologia .NET Langua-ge Integrated Query (LINQ). An-che ATLAS, estensione del mo-tore di ASP.NET per supportare il tanto discusso AJAX (Asyncro-nous Javascript And XML), si è fatto spazio fra le numerose ses-sioni dell’evento. Infine per la parte sistemi sono stati presenta-ti Windows Vista e Windows Lon-ghorn Server. Di seguito parlere-mo di alcuni di questi argomenti in maggiore dettaglio.

Windows WorkflowFoundation

Da alcuni mesi ormai si parlava in modo informale di un possibile rilascio, da parte di Microsoft, di un motore di workflow integrato nel sistema operativo Windows e distribuito gratuitamente agli utenti del sistema stesso. In que-sta PDC è stato definitivamente svelato il progetto Windows Work-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 prossimo anno e pare che sarà offerto gratuitamente, un po’ come è stato per Windows Sha-repoint Services rispetto a Win-dows Server 2003. Si tratta di un

Paolo Pialorsi è un consulente e autore specializzato nello

sviluppo di Web Service e soluzioni Web con il Framework

.NET di Microsoft. Lavora nell’omonima società Pialorsi Sistemi

S.r.l. e fa parte del gruppo DevLeap. Può essere contattato via

email: [email protected]. Paolo mantiene un blog all’indirizzo:

http://blogs.devleap.com/paolo/ .

SPECIALE

Reportage da PDC 2005

a cura di DevLeap

Dall’11 al 16 settembre 2005 si è tenuta a Los Angeles la Professional Develo-

per Conference 2005, organizzata da Microsoft Corporation.

Page 9: v2005 05 vbj65

9N. 65 - Settembre/Ottobre 2005 VBJ

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

hoc in Windows Sharepoint Services, Web Servi-

ce; ecc. L’hosting dei flussi è altrettanto variabi-

le e dipende dal particolare tipo di implementa-

zione che si vuole realizzare. Al minimo possia-

mo creare un’applicazione Console, comandando

da codice il flusso, oppure possiamo definire ap-

plicazioni Windows Forms o Web, eventualmen-

te utilizzando in questo secondo caso il motore

di Sharepoint 3.0, come vero host dei flussi. Lo

storage dei flussi e dei loro stati di avanzamen-

to è personalizzabile e configurabile. Possiamo

appoggiarci a semplici flussi in memoria, sen-

za alcun tipo di persistenza, oppure è possibile

serializzare i flussi in file XML su disco (o altri

storage). Per scenari più complessi, dove deve

essere garantito un elevato livello di affidabili-

tà, c’è la possibilità di utilizzare Microsoft SQL

Server come storage permanente, transaziona-

le e sicuro dei dati di WWF. Operativamente la

creazione di un flusso, per quanto si è visto in

una prima versione beta, è realizzabile utiliz-

zando una delle seguenti strade:

• Sviluppo di codice .NET su misura. Soluzio-

ne molto versatile, ma relativamente impe-

gnativa, oltre a richiedere uno sviluppatore

.NET per poterla realizzare;

• Disegno del flusso con la prossima versione

di FrontPage (quella che sarà presente in Of-

fice 12 e che non ha quasi più niente a che

vedere con FrontPage attuale) tramite l’uti-

lizzo di un wizard grafico su più passi;

• Definizione del flusso tramite Visual Studio

2005 (qualsiasi versione, anche le Express

gratuite) utilizzando un apposito designer,

integrato con l’IDE. In questo caso è pre-

vista la scrittura di piccole porzioni di co-

dice, associate ai singoli eventi del flusso.

Tutti i flussi, a prescindere da come ven-

gono disegnati, sono rappresentabili e/o

esportabili in formato XOML, una gram-

matica XML pensata per descrivere stati,

azioni e regole del flusso. In questo modo

potremmo anche definire un flusso a parti-

re da un XML “grezzo” e da una trasforma-

zione XSLT. Si possono definire flussi a fasi

singole e con stati finiti, oppure si possono

creare flussi multi-attività e a stati variabili.

Dal momento che parte del motore di WWF

è stato “importato” e adattato dal designer

di orchestration di BizTalk Server, non ven-

gono meno alcune delle funzionalità chiave

di BizTalk, come la possibilità di interagire

con Web Service esterni e di svolgere atti-

SPECIALE

Page 10: v2005 05 vbj65

10 VBJ N. 65 - Settembre/Ottobre 2005

vità transazionali e long running, con even-

tuali compensating transaction. Non a caso

si è lasciato intendere che la prossima ver-

sione di BizTalk Server, dopo l’imminente

versione 2006, possa utilizzare direttamente

WWF per la definizione dei suoi flussi e or-

chestration.

Microsoft Office 12Office 12 sarà la release con le maggiori no-

vità percepibili dall’utente rispetto alla ver-

sione precedente sin dai tempi di Office 97.

Il motivo è che l’interfaccia utente cambia ra-

dicalmente: via i menu, via le toolbar, avremo

un nuovo elemento, il Ribbon, che agisce in

modo contestuale alle azioni dell’utente. Ap-

parentemente un Ribbon è una nuova forma

di toolbar, in realtà ci sono regole ben precise

su ciò che può contenere, su cosa può presen-

tare e come deve interagire con l’utente. Tec-

nicamente un Ribbon è un contenitore di Tab,

ciascuno dei quali può avere più Chunk che

a loro volta contengono oggetti di vario tipo

(Button, Label, EditBox, CheckBox, Gallery e

anche Menu). L’impatto, vedendo una foto, è

di estrema diffidenza (perché mai hanno cam-

biato tutto?). Ma l’esperienza d’uso è incredi-

bile: fondamentalmente Office 12 ha gli stes-

si comandi di controllo del layout (in Word ed

Excel) di Office 2003 (e in gran parte anche di

Office XP, 2000 e 97!) ma semplicemente... mol-

ti non sanno nemmeno dove cercarli. Sembra

di usare un prodotto completamente nuovo, le

funzionalità sono proposte esattamente quan-

do servono e in maniera intuitiva, con poche

(spesso nessuna) dialog box.

Ci si può chiedere perché si parli di interfac-

cia utente di un prodotto come Office in una

rivista di programmazione: il punto è che Of-

fice ha sempre stabilito le linee guida di in-

terfaccia utente per le applicazioni “cool” in

Windows. Non è detto che il modello di Office

12 sia sensato per un’applicazione con 10 fun-

zioni in tutto, ma molti gestionali potrebbero

trarne enormi vantaggi in termini di semplici-

tà d’uso. Ma avere uno strumento non significa

essere in grado di usarlo proficuamente: die-

tro Office 12 devono esserci anni-uomo di stu-

dio delle migliori modalità di interazione con i

singoli comandi, per arrivare ad avere qualco-

sa che sembra semplice da usare quanto una

calcolatrice. Sembra facile, ma non lo è assolu-

tamente. Dal punto di vista funzionale, Office

12 ha diversi “pilastri”: integrazione comple-

ta con SharePoint v3, integrazione di funzioni

di WorkFlow, componenti Office lato server e

funzioni di visualizzazione dati avanzate (Bu-

siness Intelligence) in Excel.

Partiamo dai componenti Office lato server:

l’idea è più o meno quella di consentire a un

utente di “pubblicare” un foglio Excel su un

server producendo pagine HTML che conten-

gono il risultato di un foglio Excel, aggiornato

in base ai dati letti dinamicamente dal server.

In altre parole, se si crea un foglio Excel che

presenta il totale delle vendite diviso per ca-

tegoria di articolo, estraendo tali informazioni

da un database relazionale o multidimensiona-

le (Analysis Services), pubblicando il foglio sul

server si ottiene una pagina HTML con i dati

aggiornati al momento della richiesta (e non

solo della pubblicazione!); tutto questo avvie-

ne senza avere sul server un’istanza di Excel,

come potrebbe avvenire oggi (ma dal punto di

vista della scalabilità si tratta di un incubo, si

mette su un server un componente pensato

per un desktop client dedicato). Questo porta

a un mondo dove gli utenti possono definire

dei report da pubblicare sulla Intranet azien-

dale usando il loro amato foglio Excel. Questa

sola funzione vale oro. La funzione di workflow

(implementata basandosi su WWF) introduce la

possibilità di definire processi di gestione do-

cumentale, ma non solo: grazie all’estendibili-

tà del WWF è possibile introdurre propri com-

ponenti nel workflow e personalizzare alcune

parti di tutto il processo. Anche qui, per il pro-

grammatore diventa banale creare l’infrastrut-

tura di workflow (quella c’è già) e ci si può con-

centrare sugli aspetti prettamente funzionali

delle attività da svolgere. Chi ha sudato anni

di lavoro su questi temi sa quanto possa esse-

re decisiva una funzionalità del genere in am-

bito aziendale: con Office 12 e Windows Vista

sarà addirittura pervasiva. SharePoint v3 è il

collante tra WWF, Office 12 e componenti Offi-

SPECIALE

Page 11: v2005 05 vbj65

11N. 65 - Settembre/Ottobre 2005 VBJ

ce lato server e vi dedichiamo un’intera sezio-

ne dell’articolo, poco più avanti. Excel 12 è il

nuovo client di riferimento per accedere ai dati

aziendali. Supporta dati relazionali e multidi-

mensionali, offre finalmente tutte le funziona-

lità di Analysis Services 2005 e Analysis Servi-

ces 2000 (Excel 2003 non consente di sfruttare

appieno le capacità di Analysis Services 2000).

Ma non basta, Excel 12 integra anche funziona-

lità avanzate di visualizzazione dei dati (oltre

a tabelle pivot e grafici, per capirci) che deri-

vano dall’esperienza di Microsoft Data Analy-

zer (il team di sviluppo di quel prodotto è sta-

to inglobato in quello di Excel già dal lontano

2001). Purtroppo su questa parte c’è ancora un

po’ di riservatezza e queste funzioni non sono

ancora state mostrate al pubblico, ma non do-

vrebbe mancare molto per qualche anteprima.

Note per chi sviluppa soluzioni con/per Office:

Office 12 sarà anche l’occasione per una nuo-

va versione, la 3.0, di Visual Studio Tools for

Office; inoltre vedremo l’erede di VBA (Visual

Basic for Applications) che si chiamerà VSTA

(Visual Studio Tools for Applications), che con-

sentirà di scrivere le macro di Office in codice

.NET. Office 12 al momento è ancora sotto stret-

tissimi NDA (Non Disclosure Agreement) e la

beta non è ancora aperta al pubblico. La Beta

1 sarà disponibile entro fine anno (si ipotizza

per i primi di dicembre) e il prodotto dovreb-

be essere rilasciato nel secondo semestre 2006.

Il commento pressoché unanime che abbiamo

raccolto in chi ha visto Office 12 all’operà si può

riassumere più o meno così: si venderà da solo.

Vedremo se si tratta di analisi accurate o è solo

il frutto dell’entusiasmo per la novità.

Windows Sharepoint Services 3.0Windows Sharepoint Services 3.0 ha destato

notevole interesse. Volendo riassumere in uno

slogan le novità di WSS 3.0 si potrebbe dire:

avrà tutto quello che oggi manca a WSS 2.0!

Volendo entrare nel dettaglio, le document li-

brary, cioè le cartelle destinate a contenere i

documenti, saranno molto più configurabili di

quanto lo siano nella versione 2.0. Per esempio

avremo la possibilità di definire permessi sui

singoli file e non solo sulle cartelle, come ac-

cade oggi. Avremo il “cestino” per recuperare i

documenti eventualmente cancellati per errore.

Potremo definire gestori di eventi multipli sul-

le liste, anziché doverci adattare ad averne al

massimo uno solo. I gestori di eventi saranno

configurabili anche sulle liste non documenta-

li. Per esempio potremo configurare un nostro

handler personalizzato che ci invii una email

ogni qual volta venga creato un contatto nella

rubrica condivisa aziendale. Proprio nell’ottica

della gestione dei dati aziendali e della creazio-

ne di un portale aziendale basato su Sharepoint,

sarà possibile collegare gli item di una lista, per

esempio la lista di contatti, con i dati presen-

ti in database esterni, come potrebbe essere il

database del sistema ERP aziendale.

Immaginate la comodità di vedere dal por-

tale l’elenco dei clienti, con i loro recapiti, ma

anche con le loro posizioni aperte (saldo dare/

avere) direttamente lette dall’ERP e aggiorna-

te in tempo reale, potendo passare con un cli-

ck alla lista di documenti (fatture, bolle, email,

fax) relative al cliente. Se poi vorremo gestire

procedure aziendali, per esempio legate all’in-

serimento di un ordine o al caricamento di un

documento da approvare, potremo attivare uno

dei workflow predefiniti e “classici” già presenti

in WSS 3.0, oppure creare i nostri con WWF, per

poi collegarli a Sharepoint. Per i programmatori

che hanno l’esigenza di estendere il motore di

WSS, un’altra novità interessante è la possibi-

lità di creare tipi di campi personalizzati, senza

più essere vincolati al solo set di dati predefini-

to. Se dovessimo trovare a oggi una carenza o

un punto debole in WSS 3.0, potremmo indica-

re l’assenza di supporto nativo per device mo-

bili. Tutto il resto di necessario, rispetto anche

alla nostra esperienza diretta con il prodotto in

versione attuale, è ormai presente nella prossi-

ma release. Il giorno in cui Microsoft dovesse

rendere accessibile WSS 3.0 a client Windows

Mobile (che ormai montano “di serie” il .NET

Compact Framework), quello sarebbe il giorno

della svolta, in cui tutte le aziende con gestio-

ne informatica delle procedure passerebbero a

Sharepoint!

Non ultimo troveremo una rinnovata interfac-

cia utente, in linea con l’evoluzione che anche

SPECIALE

Page 12: v2005 05 vbj65

12 VBJ N. 65 - Settembre/Ottobre 2005

Office 12 subirà. Il rilascio di WSS 3.0 è previsto

in concomitanza con quello di Office 12, indi-

cativamente dopo la prossima estate 2006.

C# 3.0Per gli sviluppatori .NET appassionati del

Framework e di C#, le sessioni sul futuro

C# 3.0 e sulla tecnologia Language Integra-

ted Query (Linq) sono state un cibo impagabi-

le per la mente. Quando parliamo di prossima

versione del linguaggio C# non ci riferiamo

a quella che uscirà sul mercato a novembre,

con il lancio di .NET 2.0 e Visual Studio 2005,

bensì a quella ancora successiva, indicativa-

mente prevista per il 2007/2008. La prossima

versione del linguaggio C# sarà arricchita da

una serie di funzionalità accessorie, pensate

per semplificare e rendere più rapida la scrit-

tura del codice, così come per supportare Linq,

di cui parleremo nella prossima sezione. Par-

tiamo dalle modifiche al linguaggio: sarà pos-

sibile estendere “virtualmente” tipi già defi-

niti, come se venissero definiti nuovi meto-

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.

C# 3.0

public static class MyExtension

{

public static String DoSomething(this Int32 param1,

String param2) {...};

}

public class OtherClass

{

public String Name;

}

OtherClass oc = new OtherClass();

String result = oc.DoSomething(10, oc.Name);

In questo breve esempio è definita una classe

statica di nome MyExtension, con un metodo

altrettanto statico e il primo parametro esteso

con l’informazione “this”. Nel codice poi viene

utilizzata un’istanza di una classe OtherClass

che non presenta il metodo DoSomething nel-

la sua definizione, ma sulla quale abbiamo co-

munque l’illusione di poterlo invocare, proprio

grazie agli Extension Methods, che rendono il

metodo DoSomething di MyExtension disponi-

bile su tutti gli altri tipi, purché venga importa-

to, tramite la parola chiave using, il namespace

che contiene MyExtension.

Un’altra comoda aggiunta al linguaggio sono

i “Type Initializers” e i “Collection Initializers”,

che consentono di inizializzare un oggetto sen-

za passare attraverso la valorizzazione manuale

di tutte le sue proprietà, ma nemmeno doven-

do definire una serie di costruttori ad hoc per

le varie configurazioni da inizializzare. Pensia-

mo al caso seguente:

C# 2.0

public class Cliente

{

public String Nome;

public String Cognome;

}

// ...

Cliente c = new Cliente();

c.Nome = “Mario”;

c.Cognome = “Rossi”;

Se volessimo inizializzare in modo più rapi-

do le istanze di Cliente dovremmo creare co-

struttori appositi e fornire i valori di Nome e

Cognome. Con C# 3.0 e i Type Initializers si

potrà scrivere:

C# 3.0

Cliente c = new Cliente {Nome = “Mario”, Cognome = “Rossi”};

senza avere bisogno di un costruttore dedi-

cato. Nel caso delle collezioni l’idea è la stes-

sa, ma si inizializzano elenchi di istanze:

C# 3.0

List<Cliente> clienti = new List<Cliente> {new Cliente

{Nome = “Mario”, Cognome = “Rossi”}, new Cliente {Nome =

“Luca”, Cognome = “Bianchi”}};

SPECIALE

Page 13: v2005 05 vbj65

13N. 65 - Settembre/Ottobre 2005 VBJ

Esistono poi gli “Anonymous Types”. Si trat-

ta di tipi creati automaticamente dal compi-

latore, generalmente utilizzati per il passag-

gio di dati o la creazione di sottoinsiemi di

tipi esistenti. Ripensiamo ancora alla classe

Cliente, però così definita:

C# 3.0

public class Cliente

{

public String Nome;

public String Cognome;

public String Telefono;

public List<Indirizzo> Indirizzi;

}

public class ClienteSemplice

{

public String Nome;

public String Cognome;

}

Ci sono situazioni in cui si vogliono utilizzare

solo Nome e Cognome di un oggetto Cliente,

appoggiandosi magari a un tipo intermedio, più

snello, come è il ClienteSemplice. Con la se-

guente sintassi, che utilizza i Type Initializers,

possiamo creare l’oggetto “più piccolo”:

C# 3.0

Cliente c = new Cliente {Nome = “Mario”, Cognome =

“Rossi”, Telefono = “030-123456”};

ClienteSemplice cs = new ClienteSemplice {Nome = c.Nome,

Cognome = c.Cognome};

Guardando questo codice ci rendiamo conto

che una serie di informazioni possono essere

date per scontate, ricavandole dal contesto. Il

fatto che il risultato di una nuova istanza della

classe ClienteSemplice sia memorizzato in un

oggetto di tipo ClienteSemplice è prassi comu-

ne. In C# 3.0 hanno coniato la parola chiave

var (da non confondersi né con il Variant di VB

e COM, né con var di Java o Javascript!) che

permette di lasciare al compilatore l’onere di

ricavare, in modo implicito, il tipo che risulta

dalla new. Si può inoltre omettere il nome delle

proprietà Nome e Cognome nell’inizializzazio-

ne di ClienteSemplice, in quanto viene dedot-

to dai nomi delle proprietà di c (tipo Cliente)

passate come parametri. Arriviamo dunque a

questa versione intermedia di codice:

C# 3.0

Cliente c = new Cliente {Nome = “Mario”, Cognome =

“Rossi”, Telefono = “030-123456”};

var cs = new ClienteSemplice {c.Nome, c.Cognome};

E se dessimo per scontato anche il tipo Clien-

teSemplice? In C# 3.0 possiamo definire im-

plicitamente un tipo deducendone la dichia-

razione dai parametri passati nel Type Initiali-

zer; quindi, per creare un tipo che sia sottoin-

sieme di Cliente, possiamo scrivere:

C# 3.0

Cliente c = new Cliente {Nome = “Mario”, Cognome =

“Rossi”, Telefono = “030-123456”};

var cs = new {c.Nome, c.Cognome};

Il compilatore C# 3.0 creerà per noi, in fase

di compilazione, un tipo .NET con la struttura

da noi desiderata e lo farà diventare il tipo del-

la variabile cs: nei fatti, var viene sostituito con

il nome del tipo (il compilatore ne genera uno

automaticamente). L’aspetto interessante è che

anche se apparentemente si sta utilizzando un

linguaggio “dinamico”, dove non sembra esserci

un continuo controllo sui tipi a livello dichiara-

tivo, il compilatore lavora sempre in modo for-

temente tipizzato, liberando il programmatore

dalla necessità di inventare tipi “di servizio” per

operazioni di manipolazione dei dati. Sempre a

livello sintattico sono state aggiunte le “Lamb-

da Expression”. Prese dal mondo accademico

e della ricerca, le Lambda Expression servo-

no principalmente per passare porzioni di co-

dice come parametro ad altre procedure. Par-

tiamo da un esempio più completo:

C# 3.0

string[] nomiDevLeap = { “Luca”, “Silvano”, “Marco”,

“Paolo”, “Roberto” };

var nomiLunghi = from n in nomiDevLeap

where n.Length > 5

orderby n

SPECIALE

Page 14: v2005 05 vbj65

14 VBJ N. 65 - Settembre/Ottobre 2005

select n.ToUpper()

foreach ( string s in nomiLunghi ) {

Console.WriteLine( s );

}

In pratica questo codice è esattamente iden-

tico al seguente:

C# 3.0

string[] nomiDevLeap = { “Luca”, “Silvano”, “Marco”,

“Paolo”, “Roberto” };

IEnumerable<string> nomiLunghi = nomiDevLeap

.Where( n => n.Length > 5 )

.OrderBy( n => n )

.Select( n => n.ToUpper() );

foreach ( string s in nomiLunghi ) {

Console.WriteLine( s );

}

In questo codice i metodi Where, OrderBy e

Select sono Extension Methods che lavorano

sull’array di stringhe nomiDevLeap e che ese-

guono al loro interno, tramite delegate, il co-

dice che segue il simbolo =>, cioè la Lamb-

da Expression. Tutte queste novità sintattiche

sono dovute sia alla volontà di semplificare la

scrittura del codice, sia per supportare Linq.

Come si può intuire dal codice, Linq fa anche

un grande uso dei generics sfruttando però le

Lambda Expression anziché i metodi anonimi

(come avviene spesso nelle librerie di .NET 2.0,

si pensi alla List<T>.FindAll) per sintetizzare

ancora di più il codice.

LINQIl .NET Language Integrated Query è un

progetto innovativo, che prevede l’estensio-

ne del linguaggio C# (ma anche di VB e al-

tri linguaggi .NET che lo vogliano supporta-

re) per potere scrivere all’interno del codice

query rivolte a una struttura dati generica con

una sintassi che sia ancora codice .NET, ma

simile al codice SQL che scriviamo oggi per

i database relazionali, il tutto senza modifica-

re il motore del CLR. La base dati può essere

in memoria, su un file XML o su un database

SQL Server, ma è possibile creare estensio-

ni al motore Linq, per supportare altri tipi di

persistenza. Linq permette di vedere i dati a

livello di codice come insieme di oggetti con

proprietà, anziché come tabelle con campi,

però mantenendo un legame con il substra-

to, in modo tale da poter replicare sul data-

base le modifiche apportate al modello ad og-

getti. Un aspetto interessante è la possibilità

di differire la risoluzione delle espressioni di

query. Ciò avviene con varie tecniche, anche

in funzione del punto in cui risiedono i dati.

Nel caso si voglia interrogare un db relazio-

nale, è possibile convertire la sintassi Linq

in unità minime, dette Expression, organiz-

zate in Expression Tree. In pratica le Lamb-

da Expression, anziché essere eseguite diret-

tamente, sono convertite in un “piano di ese-

cuzione” definito da questi Expression Tree,

che a loro volta sono poi convertiti in relative

sintassi SQL nel momento in cui sia neces-

sario accedere al database esterno. Il vantag-

gio di questo approccio è che si può interro-

gare un database o uno storage in generale,

appoggiandosi a modelli a oggetti fortemen-

te tipizzati, ma anche facilmente collegati alla

base dati reale. Avere un modello ad oggetti

fortemente tipizzato per gestire una base dati

vuol dire evitare potenziali problemi e avere

regole di validazione sui dati molto più rigi-

de. In pratica uno dei possibili utilizzi di Linq

è quello di creare un O/R mapper, cioè uno

strato che astrae un modello relazionale in

un modello a oggetti. In realtà questo è solo

uno degli usi possibili, precisamente DLinq,

ma Linq consente di ottenere anche altri ri-

sultati, come poter manipolare una struttura

dati XML attraverso comandi simili a SQL

(XLinq). Le attuali implementazioni di Linq

sono DLinq per accedere a basi dati relazio-

nali (al momento solo SQL Server o Access)

e XLinq per accedere a fonti dati XML. Bi-

sogna però ricordare che si tratta solo di una

Technical Preview, è evidente la possibile (e in

parte già realizzata) integrazione con WinFS e

soprattutto è importante notare come l’archi-

tettura sia completamente aperta e consenta

l’introduzione “indolore” di nuove estensioni

SPECIALE

Page 15: v2005 05 vbj65

15N. 65 - Settembre/Ottobre 2005 VBJ

(dal supporto di altri database per DLinq al-l’implementazione di astrazioni diverse o al-ternative allo stesso DLinq).

DLinq, come ogni O/R mapper, nasce per ren-dere più “semplice” l’accesso a strutture dati memorizzate in database relazionali da parte 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-ghe (anche quando usiamo stored procedure) e vengono restituite “cose” tabellari; nel 99% dei progetti che seguiamo questi dati tabella-ri vengono poi convertiti dal codice del Data Access Layer in oggetti e collezioni di ogget-ti. L’obiettivo di DLinq è semplificare questa fase sia nell’estrazione dei dati, che nell’ag-giornamento degli stessi e nello stesso tem-po semplificare l’intercettazione degli errori più comuni di “digitazione”: oggi non esistono compilatori in grado di indicare se è sbagliato il nome della stored procedure o di un para-metro oppure di un campo da estrarre.

Vediamo un esempio partendo dal classico codice C# 2.0 (in questo esempio semplifica-to e senza gestione eccezioni)

DAL e C# 2.0

SqlConnection conn = new SqlConnection();

SqlCommand cmd = new SqlCommand(conn);

cmd.CommandText = ”spListClienti”;

cmd.CommandType = CommandType.StoredProcedure;

SqlParameter par = new SqlParameter();

par.ParameterName = “@IdProvincia”;

par.SqlDbType = SqlDbType.NVarChar;

par.Size = 2;

par.Value = “FI”;

cmd.Parameters.Add(parId);

List<Cliente> listaClienti = new List<Cliente>;

conn.open();

using (SqlDataReader dr = cmd.ExecuteReader(Command

Behavior.CloseConnection))

{

int nomeOrdinal = dr.GetOrdinal(“Nome”);

int cognomeOrdinal = dr.GetOrdinal(“Cognome”);

while (dr.Read())

{

Client cli = new Cliente();

cli.Nome = dr.GetString(nomeOrdinal);

cli.Cognome = dr.GetString(cognomeOrdinal);

listaClienti.Add(cli);

}

}

Utilizzando DLinq il codice diventa qualco-sa di simile a questo

DLinq

Table<Customers> clienti = db.Customers;

Var contatti = from c in clienti where c.Provincia == “FI”

select new {c.Nome, c.Cognome}

Oltre alla semplicità del codice, è bene notare come un compilatore possa essere d’aiuto su oggetti tipizzati, intercettando errori sui nomi dei campi, sulla loro tipologia e così via.

Per descrivere il mapping fra proprietà del-le classi e entità presenti nel database vengo-no utilizzati attributi sulla classe e sulle pro-prietà esposte e non file XML come avveniva nel “compianto” progetto ObjectSpaces di cui DLinq riprende le idee di base.

L’uso degli attributi (generabili automatica-mente con un apposito tool che analizza la struttura di un database) è stato oggetto di contestazioni da parte di molti sviluppatori, ma la filosofia attuale è di mantenere DLinq il più semplice possibile; comunque l’ultima parola su questi aspetti implementativi non è ancora stata scritta, anzi. Oggi Linq è un “fe-nomeno” appena nato e in crescita, da tene-re sotto controllo. Potrebbe segnare la svol-ta nell’uso dei linguaggi e nella definizione delle architetture (che fine fa il DAL?) così come potrebbe essere abbandonato o modi-ficato pesantemente come sintassi. Dipende molto anche dai feedback che tutti noi dare-mo a Microsoft.

È bene tenere presente che se le performan-ce sono l’elemento critico di un progetto, l’ap-proccio tradizionale, soprattutto per quanto riguarda l’accesso a basi dati SQL Server, re-sterà la strada migliore.

SPECIALE

Page 16: v2005 05 vbj65

16 VBJ N. 65 - Settembre/Ottobre 2005

Sicuramente è prematuro usarlo in un qual-

siasi scenario che non sia solo sperimentale;

dare però un’occhiata e mandare dei feedback

a Redmond è il modo migliore per ottenere

fra due o tre anni un prodotto più vicino alle

reali esigenze.

Windows Longhorn Servere Windows Vista

La nuova versione di Windows (Windows

Vista e Longhorn Server) porta molte novità

dal punto di vista dei servizi, dell’interfaccia

utente e delle numerose nuove funzionalità,

tanto che saranno scritti molti libri per trat-

tarle. In questo articolo ci vogliamo occupare

degli aspetti che hanno un impatto sugli svi-

luppatori, ma che magari sono anche meno

note perché meno “coreografiche”.

Ci sono molti cambiamenti nel kernel e ai

servizi di base di Windows. Da questo punto

di vista ci saranno alcune delle più rilevan-

ti novità da quando è nato Windows NT. L’in-

tento è quello di aumentare la sicurezza, la

robustezza e le prestazioni percepite (tempi

di risposta alle azioni dell’utente) del sistema

operativo. La caratteristica secondo noi più

interessante è quella dello scheduled I/O, im-

portante anche per tutti coloro che scrivono

software che deve avere prestazioni soft real-

time, per esempio chi gestisce un protocollo

di comunicazione su seriale che richiede un

controllo sui tempi di latenza. Vediamo pun-

to per punto le novità più significative. User

Mode Driver Framework: alcuni driver si pos-

sono eseguire in modalità User, pur avendo lo

stesso modello di sviluppo; questo garantisce

che un driver così caricato non possa danneg-

giare l’intero sistema. Molti driver non richie-

dono di andare realmente in modalità Kernel

(è indispensabile solo per agganciare inter-

rupt e accedere direttamente all’I/O). Ciò au-

menta la robustezza del sistema operativo. Ri-

spondendo a una domanda è stato detto che i

driver video in Windows Vista girano in mo-

dalità utente; evidentemente una parte della

comunicazione con la scheda video è gestita

da driver a più basso livello che girano in mo-

dalità kernel e che probabilmente sono inclu-

si nel sistema operativo. Questa mossa toglie

di mezzo una percentuale enorme dei moti-

vi per cui a volte si vedono “schermi blu” (la

stragrande maggioranza sono infatti dovuti ai

driver delle schede video). Scheduler: è sta-

ta introdotta una modalità chiamata “Multi-

media Class Scheduler Service” che dovreb-

be mantenere costanti i tempi di risposta nei

processi che gestiscono elementi multimedia-

li. Scheduled File I/O: si tratta di un sistema

per dare priorità alle richieste di I/O. Questo

tipo di funzionalità era atteso da tanti anni,

adesso bisogna capire meglio come è imple-

mentato. Se funziona come deve, il risulta-

to netto è una percezione per l’utente di mi-

gliore e più rapida risposta alle proprie azio-

ni, perché attività di I/O secondarie vengono

accodate, al contrario di quanto avviene oggi

dove le richieste di I/O finiscono nella stessa

coda, indipendentemente dal fatto che proven-

gano da un processo più o meno prioritario.

Protezione da malware/rootkit: ci sono tecni-

che per controllare il codice che gira in mo-

dalità kernel e per i processi critici che girano

in modalità utente, tra l’altro usando un con-

trollo per verificare che il codice sia firmato

digitalmente. Bisognerà vedere quanto que-

sto sia realmente a prova di rootkit, ma per

lo meno si dovrebbe ridurre un po’ (anche se

non del tutto) la superficie di attacco. Servi-

zi Windows: tante, tante novità.

Le più visibili sono il delayed auto-start (il

servizio parte con un processo a priorità più

bassa di CPU e di I/O, così da non rallentare

un’eventuale operatività dell’utente) e il re-

covery automatico anche in casi diversi dal

crash (per esempio memory leak e resource

leak). Le altre novità interessano la security,

con l’isolamento della sessione in cui girano

i servizi dalle sessioni interattive e l’harde-

ning dei token e dei privilegi (questo punto

meriterebbe un intero articolo).

Registry: oltre alla funzionalità transaziona-

le (disponibile anche per il file system NTFS)

c’è la virtualizzazione, che consente di ese-

guire con utenti non-admin anche quelle ap-

plicazioni che cercano di scrivere sul Regi-

stry dove non dovrebbero: tali modifiche al

SPECIALE

Page 17: v2005 05 vbj65

17N. 65 - Settembre/Ottobre 2005 VBJ

Registry sono visibili solo all’applicazione e all’utente che le ha fatte, è come se ci fosse un registro virtuale per ogni applicazione e ogni utente. Sembra una questione banale, ma ci sono un’enormità di effetti collaterali e di situazioni particolari da considerare (per esempio, un antivirus deve intercettare tutte le chiamate come se fossero reali) che richie-dono un lavoro piuttosto complesso dal pun-to di vista implementativo.

Questo ha un impatto diretto sui program-mi che devono filtrare le chiamate al registry (gli antivirus, appunto) che dovranno adattar-si a una nuova architettura per funzionare al meglio. WoW64: Windows on Windows 64 bit consente di eseguire processi a 32 bit. Non è una vera novità perché è presente anche sulle versioni a 64bit di Windows 2003 e Windows XP già esistenti.

I driver a 32 bit non sono supportati, un’ap-plicazione a 32 bit viene caricata in un “am-biente virtuale” a 32 bit dove non si possono richiamare altre DLL a 64 bit. Lo spazio di in-dirizzamento è 2Gb o 4Gb (per le applicazioni che supportano i 3Gb, è un attributo del Por-table Executable). C’è un impatto sul Registry, nel senso che le applicazioni a 32 bit vedono una vista del Registry che consente di isola-re le applicazioni a 32 bit da quelle a 64 bit. L’interoperabilità tra 32 e 64 bit può avvenire tramite COM, ma solo con componenti out-of-process e non con componenti in-process.

WinFSLa sessione su WinFS è stata replicata per con-

sentirne la visione a tutti coloro che erano ri-masti fuori dalla sala strapiena; ciò testimonia l’interesse verso questa tecnologia annunciata a PDC 2003, disponibile nella prima “Alpha” di Longhorn (adesso Windows Vista) e poi separa-ta da quest’ultimo nell’agosto 2004.

Dall’agosto 2005 è disponibile una prima Beta di WinFS (installabile su XP SP2), non sarà in-cluso nella prima release di Windows Vista, ma sarà reso disponibile come componente aggiun-tivo. Rispetto ai file system tradizionali consen-te di categorizzare le informazioni memorizzate tramite attributi definiti in uno schema. L’idea

è spostare nella piattaforma la conoscenza dei vari attributi “dei file”, che oggi è demandata alle singole applicazioni. È possibile mettere in relazione un dato o un file con un altro. WinFS fornisce il supporto per la memorizzazione del-le informazioni comuni a più applicazioni come Contatti, Aziende, Persone: questo consente alle applicazioni e agli utenti di eseguire ricerche mirate sugli item memorizzati, di evitare di me-morizzare gli stessi dati in location diverse e di utilizzare attributi diversi per la stessa tipolo-gia di informazione. L’organizzazione delle in-formazioni si basa su schemi.

Ogni schema descrive entità come eventi, per-sone, documenti, immagini e messaggi, defi-nendo gli attributi di ognuna di esse.

Per esempio una Persona può avere più in-dirizzi di posta elettronica, mentre un’Azienda può contenere diverse entità di tipo persona. Questi schemi sono estendibili: è possibile de-finirne di propri per le proprie informazioni. WinFS consente un’organizzazione gerarchica delle informazioni e una organizzazione rela-zionale: per questo spesso si legge “Relational File System”.

Vista la sua struttura è possibile ricercare dati utilizzando query relazionali tramite il modello a oggetti esposto direttamente, ma anche uti-lizzando ADO.NET e SQL. Se uno più uno fa sempre due, avrete già capito che si potrà in-terrogare WinFS anche tramite LINQ. Ecco un esempio semplice:

Linq e WinFS

Table<Customers> clienti = db.Customers

using System.Storage;

using System.Data.Objects;

using Druker.Sales;

SalesData sd = new SalesData(salesConfig);

foreach (Customer customer in sd.Customers where

LastName=’Brunetti’) Console.WriteLine(customer.FirstName);

// Aggiunta di un cliente

Customer cliente = new Customer(id, Nome, Cognome);

sd.Customers.Add(cliente);

sd.SaveChanges();

SPECIALE

Page 18: v2005 05 vbj65

18 VBJ N. 65 - Settembre/Ottobre 2005

Lo store WinFS è transazionale, consentendo l’esecuzione di operazioni utilizzando i classi-ci metodi BeginTransaction, CommitTransac-tion e AbortTransaction.

ATLASATLAS è un’estensione del motore di

ASP.NET per supportare il tanto discusso AJAX (Asyncronous Javascript And XML). Utilizzan-do oggetti server, simili ai Web Control, è in grado di produrre interfacce web che eseguo-no richieste a servizi esposti, senza eseguire i classici POST http. In pratica questi controlli inviano al client la “Client Script Library”, ba-sata appunto su Javascript, che fornisce una serie di servizi per invocare tramite XMLHt-tp la parte server.

Le richieste di informazioni passano da un Service Bridge (che insieme alla script library è incluso nel file AtlasCore.js) lato client, che a sua volta invoca i servizi server side. I servi-zi server-side possono essere i classici ASMX oppure servizi WCF (Indigo).

Grazie all’integrazione con ASP.NET 2.0, pro-xy e librerie lato client vengono generati in au-tomatico e sfruttano nativamente i moduli di autenticazione, autorizzazione e caching clas-sici di ASP.NET 2.0. I Web Service in un’appli-cazione ATLAS producono il codice javascript lato client in base ai metodi esposti dal web service stesso.

Allo sviluppatore dell’interfaccia utente non resta che scrivere le righe di codice Javascript che invocano i metodi esposti per far scatena-re la richiesta in background e utilizzare i dati per modificare l’interfaccia utente; molti con-trolli presenti in ATLAS (si utilizzano come i normali controlli asp: <atlas:TextBox>) ese-guono già queste operazioni in automatico. Sono presenti anche numerosi controlli che effettuano binding su tabelle HTML eseguen-do dietro le quinte le operazioni più comuni di inserimento, modifica e cancellazione. Anche i Validation Control possono sfruttare questa tecnologia per eseguire validazioni sui dati nel database senza eseguire POST. È disponibile uno starter kit [4] e nel 2006 dovremmo avere presto una prima beta “GoLive”.

Expression Interactive DesignerDurante la plenaria e con un paio di sessioni de-

dicate sono stati presentati i nuovi prodotti del-la famiglia Expression Web Developer. L’obietti-vo è fare un salto in avanti nella presentazione dei dati all’utente: il tema ricorrente degli ultimi anni (ma lo sarà anche per i prossimi) è “Enrich User Experience”. La famiglia dei prodotti com-prende Quartz Web Designer, Acrylic e Sparkle. Quartz Web Designer è il nuovo strumento per disegnare interfacce utente web che dovrebbe finalmente rendere più semplice la difficile in-terazione fra sviluppatori web, grafici, sviluppa-tori server-side e IT manager. Come prima cosa Quartz genera codice molto pulito e aderente a XTHML 1.0 sia Transitional che Strict, può uti-lizzare le diverse tecniche di posizionamento dei tag (dalle classiche tabelle a CSS-P) per lavora-re con vari browser. Con diversi “simulatori di browser” è in grado di effettuare una preview del risultato molto più aderente alla realtà: è possibile anche effettuare prove di binding con dati reali presenti in una sorgente dati qualun-que per testare il risultato senza dover portare le pagine su un server web. Code snippet e In-tellisense aiutano nella scrittura del codice di markup e di binding. Acrylic è invece uno stru-mento grafico per creare immagini e animazioni vettoriali o classiche; l’alternativa a PhotoShop per capirci. Acrylic è il secondo nato della fami-glia, e anche l’unico attualmente in Beta e sca-ricabile gratuitamente da www.microsoft.com/expression. Si tratta di un tool espressamente dedicato ai grafici. Affronta in modo “ibrido” la definizione di layer, ibrido perché permette di lavorare sia con vector-layer che con pixel-layer per consentire in qualsiasi momento di trasfor-mare un layer da un tipo all’altro. Tra le featu-re di rilievo segnaliamo elevate performance nel pixel painting, modifica delle dimensioni (size e dpi) di un documento, brushes, strokes gra-dient, pattern classici da strumento per dise-gnatori e la capacità di modificare il canale al-pha di un layer nella clipboard, utile per creare sfondi semitrasparenti da incollare in presenta-zioni Powerpoint o altri documenti.

La caratteristica di maggior interesse per gli sviluppatori è senz’altro la funzione di esporta-

SPECIALE

Page 19: v2005 05 vbj65

19N. 65 - Settembre/Ottobre 2005 VBJ

zione del layout finale in linguaggio XAML, so-lida base della piattaforma Windows Presenta-tion Foundation. Sarà così possibile integrare i grafici nel totale processo produttivo di un’appli-cazione Windows e non solo, come adesso, nella prima fase creativa del progetto. Sparkle, rea-lizzato completamente con Windows Presenta-tion Foundation, è il tool fondamentale per de-finire in modo visuale le interfacce utente del-la prossima generazione.

Le caratteristiche più interessanti sono l’im-portazione e la combinazione di elementi vet-toriali e bitmap, pieno supporto ai modelli 3D (geometry, materials, texture, camera, trasfor-mazioni XYZ ecc) realizzabili da zero o impor-tabili da famosi tool di terze parti.

Sarà facile definire animazioni 2D o 3D, grazie a comode form per realizzare timeline in modo intuitivo e alle funzioni rec-move-play dello stru-mento. Piena integrazione con le funzionalità le-gate a video, è infatti possibile “applicare” un vi-deo, come se fosse una texture 2D, a qualunque oggetto. Le avanzate caratteristiche tipografiche di Windows Presentation Foundation sono pie-namente supportate dal tool. Sparkle è un’appli-cazione dedicata ai designer professionisti, ma semplifica anche la vita agli sviluppatori .NET con comode toolbox per inserire controlli “tra-dizionali” (Canvas, DatePicker, Button, Textbox ecc.), creare controlli compositi unendo diversi oggetti semplici, applicare “trigger” per modi-ficare l’aspetto dei controlli in modo condizio-nale o definire sintassi di binding a design time con tanto di preview.

Il tool permette di definire sia l’aspetto del-l’applicazione sia il suo comportamento, con-sentendo l’editing dei file di code-behind C# o VB.NET; tali file ovviamente possono essere condivisi con Visual Studio 2005 per la gestione completa di un’applicazione enterprise. Signifi-cative le funzionalità legate al deployment per distribuire sia applicazioni stand-alone che ex-press application, ovvero applicazioni “ospitate” da Internet Explorer. Nascerà quindi un nuova categoria professionale di sviluppatori dell’in-terfaccia utente.

Chi saranno i pionieri di questa nuova occupa-zione: grafici evoluti o sviluppatori stanchi del

solito codice? Su Internet [5] si può avere una preview online delle funzionalità di questa fa-miglia di prodotti.

System.Transaction 2.0La versione 2.0 di .NET ha fatto un passo avan-

ti nella gestione delle transazioni: non occorro-no più componenti basati su Enterprise Servi-ces (e quindi COM+) e si è semplificata (e al-leggerita dal punto di vista dell’esecuzione) la gestione da codice. Quindi? Dalla Beta2 di Win-dows Vista e ovviamente in Longhorn Server sia il file system NTFS che il Registry saran-no transazionali!

Questo rende più semplice la scrittura di ap-plicazioni che gestiscono immagini: viene in mente un sito web con immagini memorizza-te sul file system e dati associati memorizzati in un database.

È possibile abbracciare sotto un’unica transa-zione la scrittura dell’immagine e dei dati nel DB. Le transazioni possono abbracciare SQL 2005 nativamente, MSMQ e SQL 2000 trami-te l’utilizzo trasperente del buon vecchio Mi-crosoft DTC.

ConclusioniÈ stata una PDC interessante e densa di no-

vità e informazioni utili. Ora ci aspettano cir-ca 2 anni di consolidamento delle conoscenze attuali, relativamente a .NET 1.x e .NET 2.0 durante i quali vedranno la luce WinFX, Win-dows Vista, Longhorn Server, Sharepoint 3.0, C# 3.0 e forse Linq.

In un certo senso possiamo affermare di aver dato uno sguardo attraverso una finestra che ci ha permesso di sapere come saranno i pros-simi 2 o 3 anni.

Ne è valsa decisamente la pena per non far-si trovare impreparati!

Riferimenti[1] http://www.windowsworkflow.com/[2] http://msdn.microsoft.com/winfx/[3] http://www.microsoft.com/windows/[4] http://atlas.asp.net[5] http://www.microsoft.com/products/

expression/en/default.aspx

SPECIALE

Page 20: v2005 05 vbj65

20 VBJ N. 65 - Settembre/Ottobre 2005

Il supporto base che VB6 offre, soprattutto al

programmatore neofita, per riprodurre un file

multimediale è il controllo ActiveX MS Multi-

media Control. Tutti i programmatori VB si sono

imbattuti in questo controllo e ne hanno potuto

apprezzare la semplicità d’utilizzo. Tuttavia esso

non è sufficiente per ogni tipo di applicazione.

Si vuole allora esaminare la libreria “winmm”, che

può risultare utile nell’ambito di applicazioni dai

contenuti multimediali più sofisticati.

L’articolo è rivolto, soprattutto, ai neofiti dello

sviluppo software in VB6.

Eseguire file AVI con VB6In questo caso, l’applicativo di esempio riguar-

derà la realizzazione di un lettore di file .avi, che

consente di effettuare le seguenti operazioni:

• Esecuzione in Finestra

• Esecuzione FullScreen

• Stop/Pausa

L’applicativo sarà altresì com-

pletato da funzioni di apertu-

ra e chisura del file. La libreria

“winmm” consente di riprodur-

re e registrare file audio, midi,

e CD musicali. Il Form del Pro-

getto si presenta come in Figu-

ra 1. Per cominciare occorre di-

chiarare le variabili e le funzio-

ni che entrano in gioco nell’ap-

plicativo (Listato 1) dove:

• nome_file: è il nome del file

che dovrà essere aperto e ri-

prodotto;

• comando: è il tipo di coman-

do che si vuole eseguire sul

file .avi;

• valore_ritorno: è il valore

che la funzione “mciSend-

String()”, restituisce all’uten-

te a seconda dell’operazione

da effettuare.

Anzitutto è necessario caricare

un file .AVI. Il controllo Com-

mon Dialog permette l’impo-

stazione dei filtri della tipolo-

gia del file e la procedura di

apertura (Listato 2). Si noti

che nella procedura di apertu-

Controlli multimediali

in Visual Basic 6

di Fabio Fabozzi

MULTIMEDIA

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.

Fabio Fabozzi è progettista/sviluppatore software presso la S4BT s.rl. di Latina, azienda che produce software in ambito farmaceutico. È autore del libro”Intelligenza Artificiale con Visual Basic”, edito dal Gruppo Infomedia e collabora con le riviste del gruppo come articolista. Tra i suoi principali interessi: scienze cognitive, software per la disabilità, in-telligenza artificiale, crittografia, studio dei sistemi caotici, applicazioni per calcolatori palmari. Studia Psicologia dei Processi Cognitivi presso la Facoltà di Psicologia1 dell’Uni-versità “La Sapienza” di Roma. Può essere contattato via e-mail all’indirizzo [email protected]

Page 21: v2005 05 vbj65

21N. 65 - Settembre/Ottobre 2005 VBJ

trà rendere conto di quan-

to poco tempo e con quan-

te poche righe di codice è

possibile scrivere un’appli-

cazione multimediale (Li-

stato 3). Prendiamo ora in

considerazione il comando

“Play video”. Tale coman-

do, oltre ad eseguire un

file video desiderato, lo

colloca in finestra “tiled”,

cioè adatta alle dimensio-

ni proprie di quel file AVI.

L’effetto, che molti di voi

avranno visto, è quello vi-

sibile in Figura 2.

Tuttavia, però, potrebbe

essere desiderabile aprire

un file AVI direttamente

all’interno di un control-

lo PictureBox e, quindi, adattare le dimen-

sioni del file alle dimensioni del controllo

stesso. Ciò consente di creare un applicativo/

visualizzatore, discreto e sofisticato. La pro-

cedura che andiamo ad esaminare consente

anche di poter creare un logo roteante per un

applicativo. Tale logo, appunto, potrebbe es-

sere proprio un file AVI, di modeste dimen-

sioni, che viene mandato in playback con ri-

petizione. Partiamo proprio da questo pun-

to, cioè, dalla ripetizione di un file AVI e dal-

la sua implementazione. Ripetere un file AVI

all’infinito è una cosa molto semplice, basta

aggiungere la parola “repeat” al comando e il

gioco è fatto:

comando = “Play video” + “ repeat”

ra del file, il nome va tratta-

to in questo modo:

nome_file = Chr$(34) + nome_file +

Chr$(34)

Se si omette Chr$(34) – ossia

gli apici – il file verrà aperto

ma non letto. Si noti la sintas-

si del comando “Open”:

comando = “open “ + nome_file + “

alias video”

Si può notare, nell’ultimo

spezzone della riga di coman-

do, la dicitura “ alias video”. In

questo caso, il sistema, darà ad

un file .AVI di un certo nome,

il nome generico di “video”, su

cui verranno svolte tutte le operazioni a segui-

re. Tale nome, è comunque definibile dall’uten-

te: se avessi messo “alias cipolla”, avrei mani-

polato un file video con l’alias di “cipolla”. Per

eseguire un comando, sia esso un’esecuzione

FullScreen, normale o lo stop, viene utilizza-

ta la seguente sintassi:

comando = “<denominazione del comando> video”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

Questa sintassi è la stessa che già abbiamo

visto per l’apertura del file e, come si può no-

tare, è molto simile per gli altri comandi che

vengono lanciati. Voglio riportare tutti i co-

mandi che fanno parte di questo applicativo

di esempio. In questo modo, il lettore si po-

MULTIMEDIA

Li sta to 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 StringPrivate valore_ritorno As LongPrivate comando As String

Fi gu ra 1 Applicativo prjAVI

Page 22: v2005 05 vbj65

22 VBJ N. 65 - Settembre/Ottobre 2005

Ricordatevi di rispettare lo spazio che inter-corre tra l’apice e l’inizio della parola “repeat”. Ora, la cosa più impegnativa sarà scrivere del codice che vada ad adattare un filmato AVI al-l’interno di una PictureBox. Consiglio di dise-gnare il controllo PictureBox in un nuovo Form, perché la procedura di apertura del file è legger-mente diversa da quella usata fino ad ora. Pri-ma di tutto copiate nelle dichiarazioni del nuo-vo Form le variabili e le funzioni precedenti ed aggiungete queste nuove variabili:

Const WS_CHILD = &H40000000

Private Height As Long

Private Width As Long

A questo punto, è possibile defini-re la procedura di apertura del file, che sarà quella riportata nel Listato

4. Dopo la fase di apertura, si passa alla fase di ridimensionamento del filmato AVI e del “filling” del con-trollo PictureBox (Listato 5). Una volta completate queste due proce-

dure, si può riprodurre il file in questo modo:

comando=”Play AVIFile”

Riproducendo un file AVI in una Picture-Box e con ripetizione (si ricordi l’aggiunta del comando repeat), è possibile adornare l’applicazione di un eventuale cliente con un logo animato creato “ad hoc”. Con que-sto si conclude la panoramica sulla riprodu-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-le adornare l’applicati-vo creato per un clien-te. Per ciò che concer-

Fi gu ra 2 Riproduzione del file in “tiled window”

Li sta to 2 Procedura di apertura del file .AVI

Private Sub Command2_Click() cd.Filter = “(*.avi)|*.avi” cd.FilterIndex = 0 cd.FileName = “” cd.ShowOpen nome_file = cd.FileName nome_file = Chr$(34) + nome_file + Chr$(34) comando = “open “ + nome_file + “ alias video” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

MULTIMEDIA

Page 23: v2005 05 vbj65

23N. 65 - Settembre/Ottobre 2005 VBJ

ne i suoni, la loro importanza è di

gran lunga maggiore. Si pensi, ad

esempio, a tutte quelle applicazio-

ni critiche, in cui chi utilizza un sof-

tware ha bisogno di segnali, di allar-

mi, di avvisi. In questi contesti, po-

ter riprodurre un suono è una com-

ponente essenziale. Al di là di tutte

queste implicazioni, passiamo alla

riproduzione e all’esecuzione, più in

generale, dei suoni o dei file WAV.

La finestra del progetto di esempio

per i file WAV, sarà molto simile a

quella dei file AVI. Nel progetto al-

legato, è possibile vedere – nella se-

zione delle dichiarazioni – che que-

ste corrispondono a quelle presenti

nel progetto di esempio per gli AVI.

Le funzioni che si andranno ad im-

plementare sono le seguenti:

• Apertura di un file WAV

• Esecuzione di un file WAV

• Riavvolgimento di un file WAV

• Stop/Pausa di un file WAV

• Chiusura di un file WAV

L’apertura del file WAV è del tutto simile

a quella di un file AVI, ma cambia qualcosa

nella stringa di comando:

comando = “open “ + nome_file + “ type waveaudio alias sound”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

Ciò significa che l’alias del file waveaudio su

cui verranno effettuate le operazioni avrà l’alias

“sound”. Le funzioni che manipolano i file WAV

non sono né complesse né, tantomeno, dissimi-

li da quelle già viste per i file AVI. Una pecu-

liarità può essere rappresentata dalla funzione

di “Riavvolgimento di un file WAV”:

comando = “seek sound to start”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

Ho chiamato questa funzione “riavvolgimen-

to”, che evoca la vecchia funzione presenti sui

riproduttori a cassetta di una volta. Infatti tale

funzione riporta il file all’inizio. L’elenco com-

pleto delle funzioni di base è visibile nel Lista-

to 6. Una funzione particolare può essere quella

di dare la possibilità all’utente di registrare un

file audio. Le modifiche da fare, a tale propo-

sito, sono poche. Basta aggiungere due Com-

mandButton sul form del progetto che porti-

no ad esempio queste due etichette:

• Registra WAV

• Salva file registrato

Li sta to 3 Funzioni di manipolazione di un file AVI

Private Sub Play() comando = “play video” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Play_FullScr() comando = “play video fullscreen” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Chiudi() comando = “close video” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Stop() comando = “stop video” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Li sta to 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

MULTIMEDIA

Page 24: v2005 05 vbj65

24 VBJ N. 65 - Settembre/Ottobre 2005

Si evince che la registrazio-

ne è suddivisa almeno in due

fasi; in realtà il processo è leg-

germente più lungo ma non

complicato. Se è stato carica-

to precedentemente un suo-

no, lo si chiude e se ne crea

uno vuoto disponibile per la

registrazione:

comando = “close sound”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

comando=”open new type waveaudio alias suono”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

Il passo successivo consiste nella registra-

zione vera e propria del suono, che è molto

semplice:

comando = “record sound”

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

Si registra il suono desiderato per quanto

si vuole.

Quando si vuole interrompere la registrazio-

ne, si utilizza la funzione di “Stop” presente

nel Listato 6. Per salvare il suono si utilizza

questo semplice comando:

comando = “save sound” + nome_suono

valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)

dove nome_suono è una variabile di tipo

String, in cui è stato immesso un nome da

inputbox o da textbox, una fun-

zionalità semplice da implemen-

tare nell’applicativo.

Questo conclude la panoramica

relativa alla manipolazione dei

file WAV.

ConclusioniAbbiamo visto solo alcune delle

funzionalità principali della libre-

ria “winmm”.

A tale proposito, credo che quel-

le relative alla manipolazione di

suoni siano importanti per avere

informazioni e allarmi da un pro-

cesso software.

Consiglio caldamente di consul-

tare la bibliografia alla fine di que-

sto articolo, dove potete trovare al-

tre funzione relative alla riprodu-

zione dei CD o dei file MIDI, che

possono sempre risultare utili.

Bibliografia[1] Francesco Balena – I trucchi di

Visual Basic 6, Mondadori Infor-

matica, 2003, ISBN 8883314778

Li sta to 6 Funzioni di manipolazione di un file WAV

Private Sub Esegui_WAV() comando = “play sound” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Apri_WAV() cd.Filter = “(*.wav)|*.wav” cd.FilterIndex = 0 cd.FileName = “” cd.ShowOpen nome_file = cd.FileName nome_file = Chr$(34) + nome_file + Chr$(34) comando = “open “ + nome_file + “ type waveaudio alias sound” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Riavvolgi_WAV() comando = “seek sound to start” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Chiudi_WAV() comando = “close sound” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Private Sub Stop_WAV() comando = “stop sound” valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

Li sta to 5 Ridimensionamento del file AVI nella PictureBox

Private Sub Ridimensiona_In_PB( ) Height = PictureBox.ScaleHeight/Screen.TwipsPerPixelY Width = PictureBox.ScaleWidth/Screen.TwipsPerPixelX comando = = “Put AVIFile window at 0 0 “ + Cstr(Width) + “ “ + CStr(Height) valore_ritorno = mciSendString(comando, vbNullString, 1024, 0)End Sub

MULTIMEDIA

Page 25: v2005 05 vbj65
Page 26: v2005 05 vbj65

26 VBJ N. 65 - Settembre/Ottobre 2005

In questa seconda parte dedicata al nostro pro-

getto di controllo remoto in Visual Basic .NET,

spiegheremo in dettaglio il codice di implemen-

tazione della classe RemoteStructure.

Abbiamo detto che questa classe è estremamente

importante, in quanto costituisce la classe base dal-

la quale altre classi erediteranno alcune proprietà e

metodi fondamentali. Incominciamo subito a dare

uno sguardo alle linee di codice di un primo sem-

plice metodo pubblico.

Public Function getLogicalUnits() As String

oSequenzaDrives = “REPLYDRIVESSEQUENCE>”

oUnits = Environment.GetLogicalDrives()

For Each oDrive In oUnits

oSequenzaDrives &= oDrive & “*”

Next

Return oSequenzaDrives

End Function

Questo metodo, che chiamiamo getLogicalUnits,

consente di ottenere un array di tipo string conte-

nente le radici di tutte le unità logiche presenti nel

sistema della macchina controllata, quindi eventua-

li dischi fisici e partizioni logiche. Per ottenere tutto

questo è sufficiente invocare il metodo GetLogical-

Drives() della classe Environment. In questo caso,

come si può osservare, il Target (server) dovrà ri-

spondere al Controller (client)

per mezzo di un appropriato co-

mando in formato stringa (RE-

PLYDRIVESSEQUENCE>).

A questo punto dobbiamo com-

pletare la stringa di risposta con

tutte le lettere di unità individua-

te. Utilizziamo un ciclo For Each

Next per iterare automaticamen-

te l’array privato di tipo string

oUnits e collochiamo sequen-

zialmente tutti i valori all’inter-

no della nostra stringa, ciascuno

separato da un apposito caratte-

re separatore. In questo specifico

caso utilizziamo il carattere aste-

risco. A questo punto nel blocco

Select principale del server dob-

biamo collocare il codice neces-

sario per intercettare ed eseguire

questa specifica operazione.

Case Is = “GETDRIVESLIST”

writer.Write(objStruct.getLogicalUnits())

sentText.Clear()

sentText.Text = objStruct.getLogicalUnits()

I lettori più attenti certamen-

te avranno intuito che, in fase

di inizializzazione della Form1,

abbiamo già provveduto a istan-

ziare un oggetto (objStruct) dal-

la classe RemoteStructure. Non

resta quindi che invocare il me-

todo precedentemente illustrato

Controllo Remotoin Visual Basic .NET

di Stefano Corti

APPLICAZIONI

Seconda puntata

Stefano Corti si occupa di programmazione PHP e JSP lato server, della piattaforma .NET e di integrazione di sistemi legacy con le nuove realtà del web, soprattutto in ambito gestionale, bancario e finanziario. È attualmente alle dipendenze di un primario gruppo bancario italiano. Può essere contattato via email: [email protected].

Page 27: v2005 05 vbj65

27N. 65 - Settembre/Ottobre 2005 VBJ

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().

Si tratta di un me-

todo pubblico che

restituisce varie ti-

pologie di informa-

zioni su file e directory residenti sulla macchi-

na remota. Questo metodo utilizza il metodo

privato getInformation(). Ci sembra opportuno

ricordare che getInformation() viene dichiara-

to Private dal momento che deve essere acces-

sibile solo all’interno della classe nella quale

viene definito, poiché i valori restituiti ven-

gono utilizzati esclusivamente da altri metodi

implementati all’interno della classe medesi-

ma. Al metodo GetInformation() viene passa-

to, per riferimento, il contenuto della variabile

stringa privata oFileDirName. Tale variabile,

come abbiamo visto, viene già inizializzata al-

l’interno del costruttore sovraccarico della no-

stra classe, ma anche all’interno del codice di

implementazione della proprietà Profile, come

si può chiaramente evincere osservando la se-

guente porzione di codice

Sub New()

Me.oFileDirName = “C:\”

End Sub

Sub New(ByVal FileName As String)

Me.oFileDirName = FileName

End Sub

ed iniettare nel socket di flusso la stringa così

ottenuta. Vediamo ora ciò che avviene nel pro-

gramma Controller.

If job(0) = “REPLYDRIVESSEQUENCE” Then

Dim a_delimStr As String = “*”

Dim a_delimiter As Char() = a_delimStr.ToCharArray()

Dim a_splitResult As String() = Nothing

a_splitResult = job(1).Split(a_delimiter)

Dim a_inList As String

ListView1.Items.Clear()

For Each a_inList In a_splitResult

ListView1.Items.Add(a_inList)

Next

End If

Anche in questo caso abbiamo previsto una

serie di condizioni If End If per analizzare tutti

i comandi provenenti da Target, laddove ogni

comando è contenuto nell’array job con indi-

ce 0 e i relativi parametri in indice 1. Tutte le

unità logiche trasmesse (separate dall’apposito

carattere separatore) devono popolare un con-

trollo ListView che chiamiamo ListView1. Tut-

te le lettere di unità contenute sequenzialmen-

APPLICAZIONI

Fi gu ra 1 I controlli per la gestione dei file

Page 28: v2005 05 vbj65

28 VBJ N. 65 - Settembre/Ottobre 2005

Public Property Profile() As String

Get

Return oFileDirName

End Get

Set(ByVal Value As String)

oFileDirName = Value

Set

End Property

In questo modo, la variabile privata oFileDir-

Name contiene sempre un percorso assoluto al-

l’interno del file system della macchina Target

che punta direttamente ad un qualsiasi file o ad

una qualsiasi directory. Il nostro metodo privato

utilizza una serie di metodi esposti dalla classe

File appartenente al namespace System.IO per

ricavare informazioni dettagliate su un particola-

re file o su una specifica directory, come ad esem-

pio la data di creazione, di modifica e dell’ultimo

accesso. Questi dati vengono restituiti dal meto-

do getFilesAndDirectories() che esegue un’anali-

si approfondita sulla tipo-

logia del file, tentando an-

che di eseguire una lettu-

ra, nel caso si tratti di un

file di testo (quindi non

file binari), ed eseguendo

un’esplorazione in profon-

dità nel caso che il percor-

so il questione non sia un

file bensì una directory. Ve-

diamo in dettaglio queste

funzionalità analizzando il

Listato 1.

Prima di tutto dobbiamo

stabilire se il percorso con-

tenuto nella variabile pri-

vata oFileDirName punta

ad un file oppure a una di-

rectory. Possiamo nuova-

mente utilizzare un meto-

do della classe File per ot-

tenere questo scopo. Rite-

niamo opportuno ricordare

che la classe File della FCL

(Framework Class Library)

del .NET Framework espo-

ne esclusivamente membri

statici, quindi non è necessario istanziare oggetti

da questa classe, bensì è possibile invocare di-

rettamente il metodo che ci interessa, passan-

do l’argomento al parametro del metodo stesso.

Utilizziamo, ad esempio, il metodo pubblico Exi-

sts() passando come argomento della funzione

il percorso all’interno del file system, prestando

particolare attenzione che il parametro specifi-

cato sia formalmente corretto, altrimenti verrà

generata un’eccezione che il nostro codice non

sarà in grado di intercettare e gestire adeguata-

mente. Il metodo Exists() restituisce un valore

boolean, quindi otteniamo True nel caso il pa-

rametro passato punti ad un file realmente pre-

sente sul computer, oppure False in caso con-

trario. Vediamo ora di applicare lo stesso me-

todo alla classe Directory che si comporta esat-

tamente come la classe File, esponendo quindi

una nutrita seria di metodi statici per il tratta-

mento delle directory. Nel caso il percorso spe-

cificato punti ad una directory – cosa che pos-

APPLICAZIONI

Li sta to 1 Il metodo pubblico getFilesAndDirectories() della classe Remote

Structure

Public Function getFilesAndDirectories() As String If File.Exists(oFileDirName) Then oReturned = GetInformation(oFileDirName) Try oStream = New StreamReader(oFileDirName) oReturned &= oStream.ReadToEnd() Catch ec As IOException oReturned &= “Errore di I/O su file: “ & ec.Message Catch ec As ArgumentException oReturned &= “Errore Intercettato: “ & ec.Message End Try ElseIf Directory.Exists(oFileDirName) Then Dim i As Integer Dim h As Integer oReturned = GetInformation(oFileDirName) oDirectoryList = Directory.GetDirectories(oFileDirName) oDirectoryFileList = Directory.GetFiles(oFileDirName) oReturned &= vbCrLf & _ “Contenuto della Directory: “ & vbCrLf For i = 0 To oDirectoryList.Length - 1 oReturned &= oDirectoryList(i) & vbCrLf Next For h = 0 To oDirectoryFileList.Length - 1 oReturned &= oDirectoryFileList(h) & vbCrLf Next Else oReturned &= “Errore: “ & oFileDirName & “ non trovato.” & vbCrLf End If Return oReturnedEnd Function

Page 29: v2005 05 vbj65

29N. 65 - Settembre/Ottobre 2005 VBJ

siamo sempre verificare con Exists() – inizializ-

ziamo due variabili di tipo Integer i e h. Innanzi

tutto invochiamo sempre il nostro metodo priva-

to getInformation() per ottenere informazioni di

base sulla nostra directory, dopo di ché dobbiamo

analizzare la directory per verificare se vi sono

contenuti dei file eventualmente insieme ad al-

tre directory. Chiamiamo quindi i metodi stati-

ci GetDirectories() e GetFiles() che restituiscono

matrici private a una dimensione di tipo string

contenenti rispettivamente la

lista delle eventuali directory

e degli eventuali file contenu-

ti nella directory analizzata. A

questo punto non ci resta che

iterare questi due array di tipo

string per mezzo di due cicli

For Next utilizzando la pro-

prietà Length (-1) per deter-

minare il numero totale degli

elementi presenti nell’array.

Tutti i file e tutte le directory

ricavate possono quindi esse-

re copiati nella variabile pri-

vata oReturned che viene uti-

lizzata per restituire il valore

in uscita dal metodo. Precisia-

mo che il metodo descrit-

to restituisce valori pura-

mente testuali che verran-

no visualizzati in un’appo-

sita area di testo all’inter-

no della GUI del Control-

ler. L’utente potrà quindi

vedere le caratteristiche

di un particolare file e i

contenuti di una partico-

lare directory senza ave-

re la possibilità di esegui-

re alcuna esplorazione

gerarchica. L’interfaccia

utente del Controller, il

cui progetto verrà tratta-

to approfonditamente in

seguito, prevede una se-

rie di schede selezionabili

mediante altrettanti Con-

trol Tabs. Una scheda par-

ticolarmente importante, alla quale facciamo su-

bito riferimento, è certamente quella contenen-

te tutti i controlli per le funzioni di file mana-

ger (vedi Figura 1). Possiamo facilmente nota-

re che la zona superiore della scheda contiene i

controlli per l’esplorazione delle directory e dei

file sul PC locale in uso, mentre nella parte sot-

tostante si possono trovare tutti i pulsanti che

consentono di eseguire le funzionalità di base

di file management sulla macchina remota. Il

APPLICAZIONI

Li sta to 3 Metodo pubblico per la rimozione di file e cartelle

Public Function deleteDirOrFil(ByVal pathTODEL As String) As String Dim retS As String = Nothing If Directory.Exists(pathTODEL) Then Directory.Delete(pathTODEL) retS = “Directory “ & pathTODEL & “ eliminata.” End If If File.Exists(pathTODEL) Then File.Delete(pathTODEL) retS = “File “ & pathTODEL & “ eliminato.” End If If retS Is Nothing Or retS = “” Then retS = “Attenzione: Il percorso “ & pathTODEL & “ non esiste.” End If

Return retSEnd Function

Li sta to 2 Gestione del comando GETREMOTESTRUCTURELIST all’interno

della struttura Select Case EndSelect

Case Is = “GETREMOTESTRUCTURELIST” If job(1) = “CONTENUTO DELLA DIRECTORY REMOTA” Then Try Dim root As DirectoryInfo = Directory.GetParent(objStruct.Profile) Dim abso As String = root.FullName objStruct.Profile = abso writer.Write(objStruct.exploreRemoteDirOrFil()) sentText.Clear() sentText.Text = objStruct.exploreRemoteDirOrFil() Catch nre As System.NullReferenceException writer.Write(“ERRORMAINDIRECTORY>NOARGS”) Catch nrg As Exception MessageBox.Show(“Eccezione Intercettata: “ & _ nrg.Message, “Eccezione Sollevata”, _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Try Else objStruct.Profile = job(1) writer.Write(objStruct.exploreRemoteDirOrFil()) sentText.Clear() sentText.Text = objStruct.exploreRemoteDirOrFil() End If

Page 30: v2005 05 vbj65

30 VBJ N. 65 - Settembre/Ottobre 2005

pulsante “Unità Logiche” ci consente di ottene-

re la lista completa delle partizioni presenti su

Target, come abbiamo in precedenza visto. Un

altro pulsante molto importante è certamente

“Esplora Elemento Selezionato”, che consente

di scendere di un livello nella scala gerarchica

del file system remoto, popolando il ListView1

con tutti i file e le cartelle presenti nel percor-

so selezionato. La pressione di questo pulsan-

te scatena un evento il cui codice associato cat-

tura il percorso assoluto presente in Listview1

e costruisce la stringa da trasmettere a Target,

facendola precedere dal comando GETREMO-

TESTRUCTURELIST>. Tale comando, unita-

mente al parametro trasmesso, viene interpre-

tato dal server mediante la consueta struttura

Select Case End Select.

Case Is = “GETREMOTESTRUCTURELIST”

objStruct.Profile = job(1)

Try

writer.Write(objStruct.exploreRemoteDirOrFil())

sentText.Clear()

sentText.Text = objStruct.exploreRemoteDirOrFil()

Catch

...

End Try

End If

In questa fase andiamo quindi ad implementa-

re il metodo exploreRemoteDirOrFil all’interno

della nostra classe RemoteStructure, in quanto,

come possiamo vedere, dovrà essere invocato

per l’oggetto objStruct di tipo RemoteStructu-

re. Si noti che la proprietà Profile di objStruct

viene impostata sulla base del valore stringa

contenuto in job(1). Tale stringa contiene il per-

corso assoluto del file o della directory da esa-

minare selezionati nella GUI del Controller. In

APPLICAZIONI

Li sta to 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

Page 31: v2005 05 vbj65

31N. 65 - Settembre/Ottobre 2005 VBJ

APPLICAZIONI

questo modo la variabile stringa privata della

nostra classe assumerà il valore di tale percor-

so. Implementiamo ora il metodo osservando

il Listato 2. Questa volta utilizziamo i metodi

di istanza della classe DirectoryInfo. Creiamo

dunque un oggetto di tipo DirectoryInfo pas-

sando come argomento del costruttore il valore

corrente della variabile privata oFileDirName.

Chiamiamo questo oggetto di. Se la directory

esiste e il percorso contenuto nella variabile

oFileDirName non punta ad un file, possiamo

iniziare a riempire la variabile privata oSequen-

zaDirFil con l’apposito comando da restituire,

mediante il nostro socket di flusso, al program-

ma Controller (REPLYREMOTEDIR>). Veri-

fichiamo quindi se all’interno della directory

corrente vi sono altre directory, mediante la

seguente linea di codice

Dim listadir As DirectoryInfo() = di.GetDirectories

Otteniamo così un array di elementi che pos-

sono essere manipolati ed iniettati sequenzial-

mente in una stringa mediante un carattere se-

paratore, tecnica che abbiamo già analizzato in

precedenza.

All’interno di questo specifico ciclo For Each

Next è importante eseguire un controllo sulla

correttezza formale del percorso assoluto del

file system e assicurarsi che la formazione del-

le stringhe che contengono i percorsi completi

delle directory siano perfettamente ricostruiti,

poiché, in caso contrario, esse verranno visua-

lizzate nel ListView1 all’interno della GUI del

Controller e, qualora selezionati per un’eventua-

le successiva operazione, l’errore si ribaltereb-

be nuovamente su Target, generando un erro-

re logico, previsto tra l’altro nelle ultime righe

di codice del Listato 2, nell’ultima condizione

Else, laddove il percorso fornito dal Controller

non sia corrispondente ad uno specifico file o di-

rectory esistenti all’interno del file system della

macchina remota. All’interno del ciclo iteratore

verifichiamo con il metodo EndsWith se l’ulti-

mo carattere della variabile oFileDirName cor-

risponda al carattere ASCII backslash (“\”). Se

il valore boolean ritornato dal metodo è True

proseguiamo la costruzione della nostra strin-

ga oSequenzaDirFil concatenando il valore re-

stituito dalla proprietà Name dell’oggetto dr di

tipo DirectoryInfo. In questo caso la proprietà

Name non restituisce il percorso completo ed

assoluto delle eventuali sottodirectory contenu-

te nella directory superiore di riferimento, ben-

sì solamente i nomi di tali cartelle. Noi abbiamo

invece bisogno di concatenare esclusivamente

percorsi completi. Tali percorsi devono inizia-

re sempre con la radice dell’unità logica di ri-

ferimento, poiché è in questo modo che vengo-

no visualizzati nel ListView1 del controller per

potere essere facilmente ritrasmessi al Target

sotto forma di concatenazioni di stringhe. Se la

nostra stringa oFileDirName non dovesse ter-

minare con il carattere backslash, è necessario

aggiungerlo, quindi concatenare il nome rela-

tivo della sottocartella individuata in ogni ciclo

dell’iterazione e infine terminare con il caratte-

re separatore asterisco.

Dim listadir As DirectoryInfo() = di.GetDirectories

Dim dr As DirectoryInfo

For Each dr In listadir

If oFileDirName.EndsWith(“\”) Then

oSequenzaDirFil &= oFileDirName & dr.Name & “*”

Else

oSequenzaDirFil &= oFileDirName & “\” & dr.Name & “*”

End If

Next

Per ottenere invece una lista completa dei

file presenti all’interno della cartella selezio-

nata, utilizziamo nuovamente il metodo stati-

co GetFiles() della classe Directory che ritor-

na una matrice facilmente attraversabile con

il consueto ciclo For Each Next. Dopo l’ese-

cuzione completa dei due cicli di cui abbia-

mo parlato, tutti i valori ricavati (in sequenza

tutte le directory, seguite da tutti i file presen-

ti nella cartella di riferimento, come sappiamo

contenuta nella variabile privata oFileDirName

che viene istantaneamente modificata in base

ai nuovi settaggi della proprietà profile) si trova-

no concatenati nella variabile stringa oSequen-

zaDirFil, il cui valore viene direttamente resti-

tuito dal nostro metodo. In ultima analisi, se il

percorso selezionato nel ListView1 punta ad un

Page 32: v2005 05 vbj65

32 VBJ N. 65 - Settembre/Ottobre 2005

APPLICAZIONI

file, tale procedimento non avrebbe senso, ra-

gione per cui ci limiteremo a ricavare le infor-

mazioni di base del file stesso invocando il me-

todo privato getInformation, precedentemente

descritto. Come abbiamo visto, se anche questa

condizione non viene soddisfatta, è facilmente

intuibile che il percorso del file system sia sta-

to trasmesso erroneamente o incompleto, caso

previsto dall’ultima condizione Else. Riteniamo

oppurtuno sottolineare l’importanza del meto-

do appena definito, in quanto, unitamente alla

proprietà Profile, ci consente di svolgere mol-

te operazioni di base su file e cartelle residenti

su Target. All’interno della struttura Select nel-

la Form1 del server, abbiamo previsto anche al-

cuni casi paricolari. Più precisamente vogliamo

gestire il caso in cui dal Controller venga gene-

rato un comando che ci chieda di risalire di un

livello all’interno della struttura gerarchica di

file e cartelle, senza modificare il codice di im-

plementazione della nostra classe.

Case Is = “UPONEREMOTELEVEL”

Try

Dim root As DirectoryInfo = Directory.GetParent(objStruct.

Profile

Dim abso As String = root.FullName

objStruct.Profile = abso

writer.Write(objStruct.exploreRemoteDirOrFil())

sentText.Clear()

sentText.Text = objStruct.exploreRemoteDirOrFil()

Catch nre As System.NullReferenceException

writer.Write(“ERRORMAINDIRECTORY>NOARGS”)

Catch nrj As Exception

MessageBox.Show(“Errore: “ & _

nrj.Message, “Messaggio di Errore”, _

MessageBoxButtons.OK, MessageBoxIcon.Error)

End Try

Non dobbiamo fare altro che invocare il me-

todo GetParent() della classe Directory passan-

do come argomento il valore (stringa) della pro-

prietà Profile dell’oggetto objStruct.

Per ottenere il percorso completo della di-

rectory così ottenuta utilizziamo la proprietà

FullName della classe DirectoryInfo. Il valore

restituito viene utilizzato per impostare nuova-

mente la proprietà Profile e quindi invocare il

nostro metodo exploreRemoteDirOrFil(). L’ulti-

mo metodo definito all’interno della classe Re-

moteStructure serve per eliminare cartelle e file

sul PC remoto.

Si tratta di un metodo molto semplice che uti-

lizza i metodi statici Delete() esposti dalle clas-

si File e Directory e restituisce un messaggio

stringa contenente l’esito positivo o negativo

dell’operazione. Si veda il Listato 3 per l’imple-

mentazione del relativo codice. In questo con-

testo, riteniamo opportuno soffermarci un poco

sul relativo codice scritto per il programma Con-

troller. Nella scheda di File Manager possiamo

trovare l’apposito pulsante la cui pressione sca-

tena l’evento richesto dalla nostra procedura.

Prima di tutto dobbiamo essere sicuri che

l’utente desideri effettivamente la cancellazio-

ne del file o della cartella selezionati nel Li-

stView1. Non appena il relativo comando vie-

ne immesso nel socket di flusso e ricevuto dal

server, questi provvederà immediatamente alla

cancellazione del file o della directory specifi-

cata nel parametro, senza alcuna possibilità di

recupero. Questa è la ragione per la quale rite-

niamo doveroso inserire una sorta di control-

lo “lato client” prima di procedere con l’invio

del comando.

Utilizziamo per questo scopo una semplice fi-

nestra di dialogo che ci chiede se siamo sicuri di

volere cancellare definitivamente sulla macchi-

na remota il file o la directory specificata.

In caso affermativo, l’esecuzione del program-

ma prosegue con il consueto blocco Try Catch,

che gestisce il codice che scrive nel socket TCP/

IP aperto la sequenza binaria corrispondente ai

caratteri ASCII della stringa che costituisce il

comando impartito insieme al relativo parame-

tro. Tale parametro, ovviamente, non sarà altro

che il percorso assoluto e completo della risorsa

selezionata nel nostro controllo ListView1.

ConclusioniNella prossima puntata descriveremo un’al-

tra importante classe del nostro progetto che

ci consente di controllare i processi in ese-

cuzione, di creare nuove cartelle e di otte-

nere particolari informazioni sulla configu-

razione del PC remoto.

Page 33: v2005 05 vbj65

33N. 65 - Settembre/Ottobre 2005 VBJ

XML (eXtensible Markup Language) ha rap-

presentato di fatto una rivoluzione nel con-

cetto di rappresentazione e di scambio dei

dati (vedi Riquadro 1). A suggerirne l’utilizzo negli

ambiti più disparati dell’informatica sono le sue pre-

ziose capacità intrinseche, come quella di astrarre il

contenuto di un documento dalla sua presentazione,

essere autodescrittivo, semplificare la condivisione

dei dati tra piattaforme indipendenti, essere leggi-

bile dall’uomo e usare una struttura gerarchica di

archiviazione dei dati. In particolare, il fatto di es-

sere un formato di dati auto-descrittivo implica la

possibilità di descrivere il medesimo dato con at-

tributi diversi: in altre parole, un dato caratterizza-

to da attributi variabili, ciò che si intende per dato

semi-strutturato (semi-structured data) o destrut-

turato. Poiché tale possibilità è sconosciuta al mo-

dello di dati relazionale, è proprio questo particola-

re aspetto dell’XML che mette in luce il vantaggio

maggiore di avere un supporto XML o, ancor me-

glio, un tipo di dato nativo XML in un database re-

lazionale puro come Sql Server. A questo proposito,

è bene tenere presente la distinzione fondamenta-

le che esiste tra database nativi XML (NDX) e da-

tabase relazionali con supporto

XML (XED), basata sul motore

di persistenza dei dati [1][2]: in

un database NDX il documen-

to XML costituisce l’unità fon-

damentale di persistenza, men-

tre in un XED la persistenza

continua ad essere affidata ad

un motore relazionale oppure

object oriented.

Il consorzio XML:DB Iniziati-

ve [3], che si occupa della defi-

nizione di una API standard per

la gestione dei database XML,

ha definito i seguenti requisiti

fondamentali per un database

nativo XML (NDX):

1. deve presentare un modello

logico per la gestione dei do-

cumenti XML e fornire stru-

menti, conformi a tale model-

lo, per memorizzare ed inter-

rogare questi documenti. Il

database può implementare

un proprio modello oppure

adottare uno di quelli dispo-

nibili come quelli utilizzati

da XPath o XML Infoset;

2. deve avere come unità fonda-

mentale di memorizzazione il

DATABASE

Supporto XML inSQL Server 2005

di Francesco Quaratino

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.

Francesco Quaratino è consulente in ambito di proget-tazione e amministrazione di database OLTP e OLAP, oltre che di applicazioni software orientati ai dati. È certificato MCDBA e sviluppa in VB6, ASP, VB.NET e ASP.NET. Può essere contattatto attraverso il sito di divulgazione infor-matica http://www.xplayn.org.

Page 34: v2005 05 vbj65

34 VBJ N. 65 - Settembre/Ottobre 2005

CREATE TABLE xml_tab

(

id INT PRIMARY KEY,

xml_col XML

)

GO

Alla stregua di un campo tradizionale del

modello relazionale, per il campo XML si

può specificare se ammette valore NULL o

meno, fornire un valore di default, e defi-

nire un vincolo CHECK.

Nell’esempio seguente viene creato un vin-

colo CHECK sul campo di tipo XML che ve-

rifica l’esistenza dell’elemento titolo. I me-

todi XML (di cui parleremo dopo) devono

essere forniti attraverso una user-defined

function:

CREATE FUNCTION udf_check_xml (@xml_col XML)

RETURNS bit AS

BEGIN

RETURN (SELECT (@xml_col.exist(‘//titolo’)))

END

GO

CREATE TABLE xml_tab

(

id INT PRIMARY KEY,

xml_col XML NOT NULL DEFAULT(‘<libro><autore/><editore/

><titolo/></libro>’)

CONSTRAINT CK_name CHECK (dbo.udf_check_xml (xml_col) = 1)

)

GO

Nel campo xml_col si può inserire un docu-

mento o frammento XML well-formed (vedi

Riquadro 2), in caso contrario l’istruzione di

inserimento/aggiornamento fallisce:

INSERT INTO xml_tab VALUES(1, ‘<libro><autore/><editore/

><titolo/></libro>’)

INSERT INTO xml_tab VALUES(2, N’<autore/><editore/><titolo/>’)

--fallisce perché il frammento XML inserito non è well-formed

INSERT INTO xml_tab VALUES(3, ‘<autore><editore></autore></

editore>’)

documento XML, allo stesso modo in cui

la tabella è l’unità di base nei database re-

lazionali;

3. deve essere indipendente dal modello fi-

sico di storage.

In un’accezione più ampia, invece, possono es-

sere considerati database XML quei database

che, pur non offrendo un tipo di persistenza del

dato XML, espongono metodi di accesso tipici

della tecnologia XML (XPath, XQuery, DOM).

Sql Server 2005 migliora il supporto XML pre-

cedentemente offerto da Sql Server 2000 intro-

ducendo il tipo di dato nativo XML e metodi di

accesso ai dati XML, proponendo un modello

già da tempo consolidato nel DBMS Oracle –

rivale di sempre e oggi più che mai.

Passato e presente di XML in Sql ServerSql Server 2000 non aveva un tipo di dato

nativo XML. Si sopperiva a questa mancan-

za con l’uso di campi di tipo TEXT oppure

con la memorizzazione in formato relazio-

nale (sempre che la struttura del documen-

to XML fosse sufficientemente semplice da

rendere possibile la memorizzazione del do-

cumento in tabelle normalizzate) [1]. Usare

campi di tipo TEXT inibisce la possibilità di

usare un linguaggio di query (XPath) sul do-

cumento salvato, e con essa tutte le potenzia-

lità che XML è in grado di esprimere, mentre

la memorizzazione in formato relazionale co-

stringe a una sorta di conversione che implica

un notevole lavoro e, comunque, fa perdere la

capacità gerarchica di lavorare con XML. Con

Sql Server 2005 si possono memorizzare do-

cumenti o frammenti XML in un tipo di dato

nativo XML (un frammento è un documento

XML privo di una elemento radice). Ciò per-

mette di creare tabelle che registrino solo dati

XML o dati XML insieme a dati relazionali,

validare dati XML attraverso gli schema, crea-

re indici sui dati XML, interrogare e modifi-

care dati con XQuery, combinare i metodi di

interrogazione dei dati XML con query stan-

dard T-Sql per scrivere query che restituisca-

no dati relazionali insieme a dati XML. Ecco

come creare un campo di tipo XML:

DATABASE

Page 35: v2005 05 vbj65

35N. 65 - Settembre/Ottobre 2005 VBJ

--fallisce perché viola il CHECK CONSTRAINT

INSERT INTO xml_tab VALUES(4, ‘<autore></autore><editore></

editore>’)

Il dato XML è registrato internamente in un

formato binario compresso per consentire un

parsing più veloce rispetto ad una rappresen-

tazione testuale. Quando il dato viene usato, è

convertito in Varchar unicode (UTF-16).

Per determinare la dimensione in byte effet-

tiva di un dato XML si può valutare la funzio-

ne DATALENGTH():

SELECT DATALENGTH (xml_col) FROM xml_tab

Il tipo di dato XML può essere adoperato ol-

tre che per creare campi di tabella, anche per

definire variabili e parametri di input e output

di stored procedure e user-defined function.

CREATE PROCEDURE sp_xml (

@x XML,

@y XML OUTPUT)

AS

...

CREATE FUNCTION fn_xml (

@x NVARCHAR(max))

RETURNS XML

AS

DECLARE @a XML

SET @a = @x

...

RETURN @a

Metodi del tipo di dato XMLPer interrogare un dato XML estraendo un

frammento o l’intero documento XML, è possi-

bile usare metodi esposti dal dato XML, i quali

accettano come parametro di input un’espres-

sione XQuery. XQuery 1.0 è un linguaggio di

interrogazione standard di dati XML definito

dal Wide Web Consortium (W3C) e basato su

XPath 2.0, un linguaggio di navigazione che

usa una sintassi path-based per l’identificazio-

ne dei nodi di un documento XML. XQuery è

un linguaggio dichiarativo, tipizzato e funzio-

nale, e trattasi, fondamentalmente, di un’esten-

sione (superset) di XPath 2.0. Sql Server 2005

supporta un sottoinsieme di XQuery 1.0 basa-

to sul draft di Novembre 2003 [4]. I metodi ap-

plicabili sul dato XML sono i seguenti: exist(),

query(), value(), nodes() e modify().

Il metodo exist() permette di valutare l’esi-

stenza di elementi o attributi nelle clausole

WHERE o nei CHECK CONSTRAINT, e re-

stituisce il valore 1 se la valutazione ha esito

positivo, oppure 0 (zero) in caso di esito negati-

vo. Di seguito, un esempio che fa uso di exist()

nella clausola WHERE di una SELECT, allo

scopo di selezionare le righe che presentano

nel campo XML denominato xml_col il valore

“Infomedia” in un qualsiasi attributo (@*) del-

l’elemento “editore”, indipendentemente dalla

posizione (//) di quest’ultimo nel dato XML.

SELECT * FROM xml_tab

WHERE xml_col.exist(‘//editore[@*=”Infomedia”]’) = 1

Il metodo query() restituisce un untyped

XML (documento o frammento), come risul-

tato della valutazione dell’espressione XQue-

ry su una lista di nodi XML. Il metodo va-

lue() restituisce un dato scalare convertito

nel tipo di dato T-SQL specificato come se-

condo argomento della funzione. Di seguito

DATABASE

Ri qua dro 1 Come nasce XML

Nel 1996, l’XML Working Group creò XML (eXtensible

Markup Language) basandosi sul meta-linguaggio SGML

(Standard Generalized Markup Language) costituito da

un insieme di regole per la creazione di linguaggi di

marcatura (markup languages). XML scaturì dal tenta-

tivo di superare le limitazioni dell’HTML, altro linguaggio

di marcatura derivato da SGML e divenuto popolarissi-

mo con la diffusione di internet. Infatti, l’HTML non è in

grado di presentare una strutturazione semanticamente

corretta delle informazioni, demanda l’elaborazione dei

dati interamente ad altri linguaggi e, soprattutto, non è

estendibile, costringendo i produttori di software a creare

propri standard. Fondamentalmente, rispetto all’HTML,

XML ha introdotto la gestione dei tag e degli attributi,

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

presentazione del documento XML attraverso fogli di stile

(style sheet) che si occupano di trasformare il documento

XML per una sua più facile comprensione.

Page 36: v2005 05 vbj65

36 VBJ N. 65 - Settembre/Ottobre 2005

due esempi che fanno uso di value() prima

nella SELECT e poi nella clausola WHERE.

SELECT xml_col.value(‘/libro[1]/autore[1]’, ‘vachar(50)’)

FROM xml_tab

SELECT * FROM xml_tab

WHERE xml_col.value(‘/libro[1]/autore[1]’, ‘varchar(50)’) =

‘F.Quaratino’

Il metodo nodes() scompone il contenuto di

un tipo di dato XML restituendo ogni elemen-

to su una riga diversa. Poiché XQuery non de-

finisce una sintassi per la modifica dei docu-

menti XML, Microsoft ha sviluppato un pro-

prio XML Data Modification Language (DML)

[6] utilizzabile dal metodo modify(), il quale

consente la modifica del dato XML accettando

come parametro di input un’istruzione XML

DML di inserimento (insert), cancellazione

(delete) o sostituzione (replace value of).

Gli indici XMLLa natura destrutturata di un dato XML de-

termina un inconveniente non irrilevante per

un database: una gestione fondamentalmente

lenta del dato. Da qui la necessità di creare de-

gli indici su un campo di tipo XML. Sql Server

2005 prevede la creazione di un indice primario

e fino a 248 indici secondari, a patto che esista

un indice primario (clustered) sulla chiave pri-

maria della tabella. L’indice primario XML in-

dicizza tutti i tag, i valori e i percorsi del con-

tenuto di un campo XML. La chiave primaria

è usata per correlare le righe dell’indice XML

con le righe della tabella di database di cui fa

parte il campo stesso. Di seguito l’istruzione T-

SQL di creazione dell’indice XML primario sul

campo xml_col della tabella xml_tab

CREATE PRIMARY XML INDEX xml_idx on xml_tab (xml_col)

GO

Dopo aver creato un indice primario sulla

colonna XML, è possibile creare indici XML

secondari per velocizzare particolari tipi di

query. Sono disponibili tre tipi di indici XML

secondari: PATH, PROPERTY e VALUE:

• PATH per le ricerche di valori quando si

conosca l’esatto percorso dell’elemento o

attributo da cercare (per esempio: SELECT

* FROM xml_tab WHERE xml_col.exist (‘/

libero[@anno = “2005”]’) = 1)

• VALUE per le ricerche di valori quando

non si conosca il nome o l’esatto percorso

dell’elemento o dell’attributo che contiene

tale valore ( è il caso delle cosiddette query

“wildcard” come: /libro [@* = “poesie”], in

cui la query cerca ogni elemento <libro>

che abbia un qualsiasi attributo che abbia

il valore “poesia” oppure (‘//libro/@genere[.

= “poesia”]’) = 1 in cui viene fornito un

path parziale attraverso //)

• PROPERTY per le ricerche di valori spe-

cificando il nome di un elemento(/libro/

autore)

Ecco la sintassi per la creazione di indici XML

secondari:

CREATE XML INDEX <index_name> on <table_name> (<xml_

column_name>)

DATABASE

Ri qua dro 2 Well-formed e Typed XML

Un documento XML si dice well-formed (ben formato) se osserva le seguenti regole sintattiche:

• tutti gli elementi devono essere chiusi da un tag di chiusura (<persona></persona> o alternativamente <persona/> se non c’è un testo e si tratta di un ele-mento foglia);

• tutti gli elementi devono essere annidati, nonché chiusi nella sequenza opposta a quella con cui sono stati aperti, quindi non ammettendo sovrapposizioni di elementi (<persona><nome></nome></persona> e non <persona><nome></persona></nome>);

• esiste un elemento root che contiene tutti gli altri;• gli elementi sono case sensitive;• il valore degli attributi deve essere racchiuso tra

apici o doppi apici.

Un documento XML si dice typed (tipizzato) se associato 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-cumento XML sia sempre conforme alle regole stabilite validandone i dati inseriti e le modifiche apportate alla struttura del documento.

Page 37: v2005 05 vbj65

37N. 65 - Settembre/Ottobre 2005 VBJ

USING XML INDEX <index_name> FOR [PATH | VALUE | PROPERTY]

ConclusioniLa combinazione di dati relazionali con dati

XML offre nuove e interessanti possibilità nel-

la modellazione dei dati, in grado di avvici-

narsi maggiormente al mondo reale sempre

suscettibile di cambiamenti. L’introduzione di

un tipo di dato nativo XML consentirà anche

ai progettisti di database che adoperano Sql

Server di progettare applicazioni molto più

flessibili, in quanto capaci di assorbire me-

glio i cambiamenti che intervengono nel do-

minio applicativo dell’applicazione, nel corso

del suo intero ciclo di vita, grazie alla possibi-

lità di modellare i dati destrutturati.

Occorre però fare attenzione a non farne un

uso spregiudicato, dettato dalla moda del mo-

mento o dalla voglia di provare ad ogni costo

il nuovo giocattolo messo a disposizione dal-

la tecnologia emergente. Sarà, quindi, buo-

na norma continuare ad usare il modello re-

lazionale per la maggior parte dei dati, intro-

ducendo campi XML per ospitare informa-

zioni non obbligatorie o che potrebbero cam-

biare col tempo.

Bibliografia e Riferimenti[1] G. Veneri – “DB e XML: prodotti”, Compu-

ter Programming/Infomedia, Maggio 2005

[2] M. Simi – “Database XML nativi”, Compu-

ter Programming/Infomedia, Maggio 2005

[3] XML:DB Initiative –

http://xmldb-org.sourceforge.net

[4] http://www.w3.org/TR/xquery

[5] M. Nunn – “Extending XML in SQL Ser-

ver 2005”, Sql Server Magazine/Penton,

June 2005

[6] P.Vithanala – “Introduction to XQuery

in SQL Server 2005”, Microsoft Corpora-

tion, June 2005 http://msdn.microsoft.com/

library/default.asp?url=/library/en-us/

dnsql90/html/sql2k5_xqueryintro.asp

[7] S. Pal et al. – “XML Best Practices for Micro-

soft SQL Server 2005”, Microsoft Corpora-

tion, April 2004 http://msdn.microsoft.com/

SQL/archive/default.aspx?pull=/library/

en-us/dnsql90/html/sql25xmlbp.asp

[8] S. Pal et al. – “XML Support in Microsoft

SQL Server 2005”, Microsoft Corporation,

May 2005 http://msdn.microsoft.com/library/

default.asp?url=/library/en-us/dnsql90/html/

sql2k5xml.asp

DATABASE

Page 38: v2005 05 vbj65

38 VBJ N. 65 - Settembre/Ottobre 2005

In ambiente Windows ci sono applicazioni più

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

fanno sentire ma per la maggior parte del tempo

non ci accorgiamo della loro presenza.

Eppure ci sono. Basta aprire il Task Manager per

vedere un lungo elenco di applicazioni in esecu-

zione… Ma chi le ha lanciate e soprattutto: cosa

fanno?

Per chi non lo avesse ancora capito, stiamo par-

lando dei Servizi Windows, quelle particolari ap-

plicazioni che girano in background per svolgere

compiti “di sistema”.

Nel presente articolo analizzeremo cosa sono e

come vengono implementati i Servizi, ne vedre-

mo i vantaggi e i vincoli e vedremo cosa il .NET Fra-

mework mette a disposizione per realizzarne uno.

Cos’è un Servizio WindowsPrima di tutto diamo una definizione di servizio.

Un Servizio Windows è un’applicazione che gira

in background e che normalmente viene manda-

ta in esecuzione non appena il

sistema operativo è avviato, in

una sessione separata da quel-

la dell’eventuale utente che si

è loggato.

Analizziamo meglio questa de-

finizione:

• Un Servizio Windows è un’ap-

plicazione che gira in back-

ground: vuol dire che il ser-

vizio non ha interfaccia uten-

te e la sua esecuzione non è

“visibile” agli utenti che uti-

lizzano il PC su cui gira;

• Normalmente viene mandato

in esecuzione non appena il

sistema operativo è avviato:

infatti i servizi sono spesso

utilizzati per quelle applica-

zioni che devono sempre

essere attive (ad esempio i

server) per cui è importante

che siano attivati dal sistema

operativo senza che ci sia un

utente che acceda e lo mandi

in esecuzione;

• Sono in esecuzione in una

sessione separata da quello

dell’eventuale utente che si è

loggato: infatti se come dice-

vamo sopra i servizi sono ap-

.NET

Sviluppare ServiziWindows con .NET

di Emanuele Delbono e Claudio Maccari

Servizi

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

Claudio Maccari, la programmazione per lui è una

passione diventata un vero lavoro. Lavora come analista,

progettista e sviluppatore di applicazioni in particolar modo

su piattaforma .NET

Emanuele Delbono si occupa di progettazione e sviluppo

di applicazioni su piattaforma Microsoft .NET. Svolge attività

di formazione e partecipa come speaker a conferenze e

workshop nazionali.

Page 39: v2005 05 vbj65

39N. 65 - Settembre/Ottobre 2005 VBJ

ce Control Manager (SCM), il Service Applica-

tion (SA) e il Service Control Program (SCP).

Il SCM è esso stesso un servizio (services.exe)

che gira con privilegi di sistema e si occupa

di gestire gli altri servizi avviandoli, ferman-

doli, mettendoli in pausa, ecc…

Il SA è il servizio vero e proprio quindi un

eseguibile avviato dal SCM che esegue le

operazioni per cui è stato scritto. Un SA avrà

sempre almeno due eventi: OnStart e OnStop.

Questi si verificheranno nel momento il cui il

servizio verrà rispettivamente avviato e fer-

mato. Il SCP è l’interfaccia che permette al-

l’utente di interagire con il servizio inviando

comandi al SCM per avviare, fermare, modi-

ficare le credenziali, ecc… del servizio.

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-

cuzione? Sarebbe cer-

tamente un problema

che renderebbe il ser-

vizio inutilizzabile. Queste caratteristiche fan-

no si che il Servizio sia ottimo per compiti la

cui esecuzione deve essere continua. Si pen-

si ad esempio ad un server web: altro non

è che un’applicazione che rimane in ascolto

sulla porta 80 ed elabora le richieste che arri-

vano dai client. Un’applicazione server (web,

POP3, ecc…) è il tipico esempio di servizio,

tant’è che Microsoft stessa ha implementato

il suo server web (Internet Information Ser-

ver) come servizio (InetInfo.exe).

Le componenti di un servizio L’infrastruttura che Windows mette a dispo-

sizione per l’implementazione e la gestione di

un servizio è composta da 3 elementi: il Servi-

.NET

Fi gu ra 1 La finestra delle proprietà del servizio

Page 40: v2005 05 vbj65

40 VBJ N. 65 - Settembre/Ottobre 2005

Di questi 3 componenti quello che il pro-

grammatore andrà ad implementare (tra poco

vedremo come) è il servizio vero e proprio

(SA) in quanto il SCM è un componente già

presente nel sistema operativo e il SCP è an-

ch’esso un’applicazione del pannello di con-

trollo di Windows, pertanto già disponibile (la

troviamo nel Pannello di Controllo | Strumen-

ti di Amministrazione).

Per la scrittura di un servizio, Visual Studio

.NET, ci viene incontro preparando parte del

codice necessario.

VS.NET crea una classe Service1 che eredita

da ServiceBase, classe base di tutti i servizi.

Di questa classe viene fatto l’override di al-

meno 2 metodi: OnStart e OnStop. Il primo,

OnStart, è chiamato dal SCM quando deve

avviare il servizio e dovrà contenere il codice

necessario allo startup delle operazioni che il

servizio deve svolgere, il secondo invece vie-

ne chiamato quando il servizio viene fermato

e deve implementare i meccanismi di chiusu-

ra e rilascio delle risorse.

Inoltre il template di Visual Studio prepa-

ra il metodo Main per l’avvio del servizio da

parte del SCM chiamando il metodo shared

Run della classe ServiceBase:

Dim ServicesToRun() As System.ServiceProcess.ServiceBase

ServicesToRun = New System.ServiceProcess.ServiceBase()

{New Service1}

System.ServiceProcess.ServiceBase.Run(ServicesToRun)

.NET

Fi gu ra 2 La console per la gestione dei servizi

Page 41: v2005 05 vbj65

41N. 65 - Settembre/Ottobre 2005 VBJ

Questo è quanto serve per avere un servizio

minimale. Oltre a questi metodi è possibile fare

l’override di: OnPause, OnContinue, OnShu-

tDown, OnCustomCommand, OnPowerEvent

per gestire finemente le risposte del servizio

agli eventi elencati.

Sviluppare il nostro primoServizio Windows

Il servizio che andremo a creare avrà il com-

pito di processare gli ordini ricevuti. Gli or-

dini sono creati da un’ipotetica applicazio-

ne dei nostri clienti ed inviati in una coda

di messaggi presente sui nostri server e ge-

stita da un’altro servizio: Microsoft Messa-

ge Queue (MSMQ). La nostra applicazione,

grazie al modello ad oggetti messo a dispo-

sizione dal .NET framework nel namespa-

ce System.Messaging, ha il compito di pro-

cessare i messaggi arrivati in coda. Iniziamo

quindi a scrivere qualche riga di codice per

implementare il servizio. Grazie ai templa-

te di Visual Studio l’infrastruttra di codice

necessaria la troveremo quasi tutta imple-

mentata. Aperto Visual Studio, dal menù File

scegliamo Progetto. Selezioniamo il proget-

to di tipo Servizio Windows e lo chiamiamo

per esempio VBJService. Rinominiamo il file

Service1.vb in MSMQWatcher.vb.

Per prima cosa possiamo notare che l’Inte-

grated Development Environment (IDE) ha

già creato gli eventi fondamentali per il no-

stro servizio ovvero OnStrat e OnStop.

Nel Listato 1 aggiungiamo agli eventi car-

dine il codice necessario per fare il log ed

utilizzare la piccola libreria (Listato 2) crea-

ta per interfacciarsi con la coda degli ordini.

Ricordiamo sempre che in un servizio l’inte-

razione con l’utente non può avere le solite

modalità come finestre e messaggi.

Ora che il nostro servizio è pronto per

l’uso, si può avviare e fermare tramite

.NET

Li sta to 1 La classe MSMQWatcher

Imports VBJService.MSQMPublic 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 SubEnd Class

Page 42: v2005 05 vbj65

42 VBJ N. 65 - Settembre/Ottobre 2005

SCP e, una volta avviato, grazie ad un ti-mer controlla la coda dei messaggi in at-tesa di ordini, inserendo un record nel log degli eventi di Windows ogni volta che vie-ne eseguita una di queste operazione. In-somma cosa volere di più da un servizio? Bene, allora perché non lanciarlo per vede-re se tutto è ok e cominciare a scrivere codi-ce più interessante? Purtroppo, a differenza della maggior parte dei progetti creati in Vi-sual Studio .NET, i progetti di Servizio Win-dows non possono essere eseguiti direttamen-te dall’ambiente di sviluppo premendo F5. È

invece necessario prima installare il servizio e poi lanciarne l’esecuzione.

Per installare Servizi Windows, il framework mette a disposizione l’utilità da riga di co-mando InstallUtil.exe. Prima di usare questo strumento però dobbiamo aggiungere ancora qualcosa al nostro servizio. Andiamo nella fi-nestra di design del servizio. Facciamo clic con il tasto destro e quindi selezioniamo la voce del menu Aggiungi programma d’installazio-

ne. Per impostazione predefinita, al progetto sarà aggiunto un nuovo componente dal nome ProjectInstaller. Questo contiene i program-

.NET

Li sta to 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

Page 43: v2005 05 vbj65

43N. 65 - Settembre/Ottobre 2005 VBJ

mi d’installazione del servizio e del processo

associato al servizio. Facendo doppio clic sul

file appena aggiunto noteremo i due oggetti.

Per quanto riguarda il ProcessInstaller dovre-

mo prestare attenzione alla proprietà Account,

ovvero l’utente con cui sarà avviato il nostro

servizio: nel nostro caso dovrà essere “Local-

Service”; mentre analizzando il componente

ServiceInstaller dovremo modificare le pro-

prietà ServiceName, Description e DisplayNa-

me che saranno i valori visualizzati nel SCP.

Ora abbiamo davvero tutto quello che serve

per installare ed eseguire il servizio. Dopo aver

compilato – per fare prima CTRL+SHIFT+B

– possiamo lanciare il Command Prompt di

Visual Studio. Una volta posizionati nella

cartella bin\debug del progetto che contiene

l’eseguibile fresco di compilazione e lancia-

mo il comando

VS Prompt

InstallUtil vbjservice.exe

Ricordiamoci che la nostra applicazione usa

il servizio MSMQ [1] (in italiano Accodamento

Messaggi). Bisogna quindi accertarsi di averlo

installato sulla nostra macchina. Ora il nostro

servizio è installato. Possiamo avviarlo usan-

do SCP oppure usando il comando

VS Prompt

net start msmqwatcher

Ora che il servizio è attivo possiamo con-

trollare il log degli eventi.

Troveremo un nuovo record che indica l’av-

vio del nostro servizio. Per rendere le cose

più interessanti possiamo riempire la coda

dei messaggi con qualche ordine da far pro-

cessare al nostro servizio.

Per far questo nell’esempio allegato all’ar-

ticolo troverete una semplice applicazione

console che una volta lanciata inserisce 10

messaggi nella coda OrderQueue (Listato 3).

Nel momento in cui il servizio trova i mes-

saggi può cominciare a fare il suo vero la-

voro. Per verificarlo controlliamo ancora il

log degli eventi dove avremo un nuovo re-

cord per ogni ordine processato dal servizio.

Una volta processati tutti gli ordini possia-

.NET

Li sta to 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

Page 44: v2005 05 vbj65

44 VBJ N. 65 - Settembre/Ottobre 2005

mo fermare il nostro servizio dal SCP op-

pure usando il comando

VS Prompt

net stop msmqwatcher

DebugIl nostro servizio è talmente semplice da non

richiede un debug; in un caso reale più com-

plesso però potremmo avere bisogno di que-

st’importante feature messa a disposizione dal

nostro ambiente di sviluppo. Per questo è bene

sapere come fare in caso di bisogno; infatti a

differenza delle altre applicazioni, se da Visual

Studio.NET premiamo F5 per mandare in ese-

cuzione il servizio, per il debugging non accade

nulla. Il debug di un servizio è un’operazione

leggermente più complessa. L’idea è di utilizza-

re il debugger dei processi di VS.NET per ag-

ganciarsi al servizio creato, quindi si inserisce

un breakpoint nel punto in cui vogliamo fer-

mare il programma (non nel metodo OnStart)

e poi facciamo partire il servizio come visto in

precedenza. A questo punto dovremo ritornare

nell’IDE e scegliere Processi dal menu Debug.

Sarà visualizzata la finestra di dialogo Proces-

si. Verificheremo che il flag Mostra processi di

sistema sia attivo.

Nella sezione Processi disponibili, faremo

clic sul processo del servizio, e ci aggancere-

mo tramite il pulsante Connetti. A questo pun-

to siamo in modalità di debug e l’esecuzione

si interromperà sul breakpoint settato prima.

Questa tecnica, benché permetta il debug del

servizio, ha alcune limitazioni. Infatti può ca-

pitare che il servizio abbia un bug nel meto-

do OnStart.

Quando andiamo ad agganciare il processo

tramite VS.NET, il metodo OnStart è stato già

eseguito e intercettare gli errori in quel meto-

do risulta quasi impossibile. Qualora fosse ne-

cessario eseguire il debug dell’evento OnStart

è possibile utilizzare una “trucchetto” molto

semplice e veloce. La prima istruzione del me-

todo OnStart dovrà essere

VB.NET

‘da utilizzare solo in fase di debug

‘Max 30 secondi altrimenti il servizio va in timeout

Threading.Thread.Sleep(15000)

Questo ci darà 15 secondi di tempo per ag-

ganciare il processo del servizio al debugger

di Visual Studio. Ricordiamoci di non andare

oltre i 30 secondi altrimenti l’avvio del servi-

zio darà errore di timeout. Così facendo bi-

sogna ricordarsi di commentare l’istruzione

prima del rilascio in produzione.

Una tecnica alternativa che permette di de-

buggare interamente il servizio, compreso il

metodo OnStart, è quello di scrivere un’ap-

plicazione Windows Forms che assume il ruo-

lo di Service Control Manager, cioè avvia il

servizio, lo ferma, ecc…

L’applicazione Windows Forms avrà inter-

faccia utente e utilizzerà il servizio come se

fosse una sua libreria chiamando i metodi

OnStart, OnStop, ecc…in questo modo ogni

eventuale errore sul metodo OnStart può es-

sere intercettato visto che stiamo debuggan-

do una normale applicazione Windows.

ConclusioniCome abbiamo visto, lo sviluppo di un ser-

vizio non è molto diverso da altri tipi appli-

cazione Windows.

Quindi se da un lato la nostra applicazio-

ne può scalare di molto, dall’altra bisogna

prima considerare alcuni punti fondamen-

tali, quali l’iterazione con l’utente e la ge-

stione degli errori.

Una nota dolente può essere l’esecuzione

del debug.

Per ovviare a questo inconveniente è buo-

na regola spostare la logica applicativa in

un componente esterno – noi l’abbiamo fatto

con la libreria che fa da proxy con MSMQ –

e testarlo separatamente tramite strumenti

di Unit Testing (per es. NUnit).

Riferimenti[1] Microsoft TechNet – Accodamento mes-

saggi http://www.microsoft.com/technet/

prodtechnol/windowsserver2003/it/library/

ServerHelp/192eb6e0-e4ac-4dd0-bc44-

dd26a43f5fa8.mspx

.NET

Page 45: v2005 05 vbj65

45N. 65 - Settembre/Ottobre 2005 VBJ

Microsoft Web Services Enhancements

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

ria per estendere il motore di Web Ser-

vice di base del Framework .NET. Giunta alla ver-

sione 2.0 Service Pack 3 [3], affiancata nell’ultimo

periodo da una Technology Preview della versione

3.0, rappresenta ormai un prodotto maturo e stabi-

le per la creazione di servizi SOAP in architettura

Service Oriented ([1] e [2]). In questo articolo ve-

dremo come utilizzare WSE2 per creare applicazio-

ni in grado di scambiarsi messaggi SOAP.

Perché WSE?La prima domanda che viene generalmente posta

quando si parla di WSE è: “Perchè WSE?”. In .NET

abbiamo infatti un motore per la creazione di Web

Service, i cosiddetti Web Service ASMX, e per mol-

ti non è chiara la ragione per cui debba esistere una

libreria aggiuntiva che li estende, a volte rappresen-

tandone un’alternativa. WSE nasce con l’obiettivo

di fornire il supporto alle specifiche più moderne

relative a SOAP e ai (Web) Service. Si tratta di una

libreria esterna al motore degli ASMX, in quanto

deve essere in grado di evolvere rapidamente e agil-

mente, senza sottostare alle regole di validazione e

rilascio del codice cui sono soggetti prodotti com-

plessi come Visual Studio .NET

e il .NET Framework. Negli ul-

timi 3 anni abbiamo utilizzato

.NET Framework 1.x e solo ora

sta per vedere la luce il .NET Fra-

mework 2.0. Nel frattempo sono

uscite diverse release di WSE di

cui 2 maggiori (WSE 1.0 e WSE

2.0) e diverse minori (vari Servi-

ce Pack), oltre a un’anteprima di

WSE 3.0. Tutte queste versioni,

rilasciate in meno di due anni,

sono il frutto della rapida e incon-

trollabile crescita di WSA (Web

Services Architecture) e di tutte

le numerose specifiche (WS-Se-

curity, WS-Addressing, WS-Atta-

chments, ecc.) ad essa collegate.

Potremmo descrivere WSE come

lo sforzo, da parte di Microsoft,

di rimanere allineata con l’evo-

luzione tecnologica della specie

(SOAP). Dall’altro lato, proprio

per come è pensato, WSE è da

utilizzare essendo consapevoli

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

loro, né come codice e funzionali-

tà, né in termini di compatibilità

binaria dei messaggi che viaggia-

no sul cavo. Anche il passaggio

.NET

SOAP Messaging

con WSE

di Paolo Pialorsi

WSE

Vediamo le principali caratteristiche di Microsoft Web Services Enhancements

dal punto di vista del SOAP Messaging.

Paolo Pialorsi è un consulente e autore specializzato nello

sviluppo di Web Service e soluzioni Web con il Framework

.NET di Microsoft. Lavora nell’omonima società Pialorsi

Sistemi S.r.l. e fa parte del gruppo DevLeap. Mantiene un

blog all’indirizzo: http://blogs.devleap.com/paolo/.

Page 46: v2005 05 vbj65

46 VBJ N. 65 - Settembre/Ottobre 2005

prevede un’architettura pesantemente basa-

ta sul concetto di messaggio, che essendo un

messaggio SOAP assume la forma di un og-

getto di tipo SoapEnvelope. Una SoapEnve-

lope non è altro che una classe, derivata da

System.Xml.XmlDocument, che fornisce al-

cune funzionalità di uso ricorrente per la ge-

stione di un messaggio SOAP. Per esempio at-

traverso un’istanza di SoapEnvelope possiamo

accedere direttamente al Body e agli Header

del messaggio SOAP. Sempre dalla SoapEn-

velope abbiamo accesso a una serie di meta-

informazioni sul messaggio, relative alla sicu-

rezza, al routing, al messaging, agli eventuali

file allegati al messaggio, ecc.

Ogni volta che un messaggio SOAP viene

gestito da WSE, esso attraversa una pipeline

di filtri, detti SoapFilter, che processano sia

in ingresso (SoapInputFilters) che in uscita

(SoapOutputFilters) le singole SoapEnvelo-

pe (Figura 1). Esistono dei SoapFilter prede-

finiti come quelli per gestire la sicurezza dei

messaggi, il loro instradamento e in caso di

esigenza il logging a fini di diagnostica. Pos-

siamo creare nostri SoapFilter derivando da

classi base molto comode.

Le SoapEnvelope attraversano queste pipe-

line in quanto il motore di WSE prevede il

concetto di SoapPort, della quale esistono di-

verse implementazioni che vedremo nel cor-

so dell’articolo. Ad ogni SoapPort sono asso-

ciate una lista (Pipeline) di filtri e un cana-

le (Channel). L’architettura di messagging di

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

• WS-Addressing

• WS-Policy

• DIME

• WS-Attachments

La preview di WSE3, ad oggi e per comple-

tezza, sostituisce il supporto agli allegati nei

messaggi SOAP, che lo scorso anno erano ge-

stiti con WS-Attachments e DIME, con la com-

patibilità con MTOM (Message Transmission

Optimization Mechanism [5]), oltre a fornire

la possibilità di essere utilizzato con .NET 2.0.

Probabilmente WSE4 non vedrà mai la luce,

infatti nel 2006 dovrebbe essere rilasciato In-

digo [7] che andrà a sostituirsi a tutte le at-

tuali tecnologie di comunicazione e che do-

vrebbe (il condizionale è d’obbligo) essere in

grado di “parlare” con WSE3.

SoapEnvelope - il cuore di WSEPer utilizzare WSE dobbiamo innanzitutto

scaricarlo da MSDN [3] - consiglio l’installa-

zione di tipo Visual Studio .NET Developer,

per avere un addin di configurazione di WSE a

disposizione nell’IDE di Visual Studio .NET -

e referenziarlo nei nostri progetti, cercando la

class library Microsoft.Web.Services2.dll. WSE

Fi gu ra 1 Flusso di un messaggio SOAP attraverso

una Pipeline di WSE

.NET

Microsoft WSE è una libre-

ria per estendere il motore

di Web Service di base del

Framework .NET

Page 47: v2005 05 vbj65

47N. 65 - Settembre/Ottobre 2005 VBJ

WSE è pensata per essere utilizzata in due

differenti modalità:

• affiancata al motore ASMX per estender-

lo, sfruttando una SoapExtension [6] lato

server e una specializzazione di SoapHt-

tpClientProtocol lato client;

• come alternativa ad ASMX, utilizzando un

motore di comunicazione ad hoc.

Il fatto che WSE2 esponga le sue funzionalità

sia come aggiunta al motore degli ASMX, che

come sistema alternativo ad essi, ci consente di

creare server e client di servizi SOAP senza bi-

sogno di un server IIS e/o ASP.NET. Da questo

momento in poi ci concentreremo sullo scambio

di messaggi SOAP, per utilizzare WSE2 come in-

frastruttura di comunicazione tra processi, ser-

vizi e sistemi senza utilizzare IIS e ASP.NET.

Questo ci consente di avere un approccio com-

pletamente orientato a SOA.

Soap MessagingIl motore di comunicazione di WSE2 si basa

sull’uso di classi derivate da SoapPort (Figu-

ra 2). Nello specifico esistono due modalità

di comunicazione, che corrispondono a due

differenti paradigmi di dialogo:

• SoapReceiver/SoapSender: prevede un si-

stema di scambio paritetico di messaggi

SOAP. Si utilizza quando si devono creare

sistemi di comunicazione monodirezionale,

oppure peer-to-peer ovvero sistemi di co-

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.

Aspetto chiave di questa architettura è il fat-

to che i protocolli di trasporto dei messaggi

SOAP sono intercambiabili ed estendibili, ri-

spetto all’architettura del singolo servizio.

Esistono diverse implementazioni per vari

protocolli di uso comune. Già WSE2 offre il

supporto per HTTP, TCP e un protocollo IN-

PROCess per le comunicazione all’interno di

uno stesso AppDomain. Esistono inoltre sulla

rete implementazioni indipendenti di MSMQ,

UDP, SMTP, ecc. Quando sviluppiamo i servi-

zi possiamo prescindere dal protocollo di tra-

sporto che andremo a utilizzare per esporli, con

un approccio pienamento SOA. Solo nel mo-

mento in cui vorremo esporre i servizi dovre-

mo preoccuparci di definire un punto di acces-

so (EndpointReference) e configurarlo affiché

utilizzi un determinato protocollo.

SoapSenderVediamo un primo esempio di utilizzo di Soa-

pReceiver e SoapSender, sfruttando il proto-

collo TCP. Immaginiamo di voler inviare tra-

mite SOAP Messaging un oggetto che rappre-

senta un ordine. Dobbiamo innanzitutto crea-

re una SoapEnvelope che descriva il messag-

gio da inviare:

C#

// Nella variabile order immagino di avere i dati di un

ordine

Order order = new Order();

order.IdOrder = 10;

order.Description = “Ordine dimostrativo 10”;

SoapEnvelope envelope = new SoapEnvelope();

.NET

Fi gu ra 2 Schema funzionale di una SoapPort in

WSE

Page 48: v2005 05 vbj65

48 VBJ N. 65 - Settembre/Ottobre 2005

envelope.CreateBody();

envelope.SetBodyObject(order, “http://schemas.devleap.com/

order”);

Con queste prime righe stiamo creando un oggetto DOM XML - ricordiamoci che SoapEn-velope deriva da XmlDocument - che avrà la struttura di una SOAP Evenlope e conterrà al suo interno l’oggetto order, serializzato con XmlSerializer, che è lo stesso motore di seria-lizzazione che utilizzano anche gli ASMX. Po-tremmo in alternativa costruire il contenuto del messaggio SOAP manualmente, creando i singoli nodi XML all’interno del Body del messaggio SOAP.

Come si vede abbiamo quindi la massima versatilità rispetto alla gestione del contenu-to del messaggio SOAP, potendo sfruttare al massimo il SOAP messaging. Per verificare cosa sta succedendo dietro le quinte, imma-ginando che il nostro ordine sia definito nel modo seguente:

C#

public class Order

{

public Int32 IdOrder;

public String Description;

}

possiamo provare a salvare la SoapEnvelope su disco e vederne il contenuto XML:

C#

envelope.Save(“order.soap.xml”);

XML (SOAP)

<?xml version=”1.0” encoding=”utf-8”?>

<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/

soap/envelope/”>

<soap:Body>

<Order xmlns:xsd=”http://www.w3.org/2001/XMLSchema”

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xmlns=”http://schemas.devleap.com/order”>

<IdOrder>10</IdOrder>

<Description>Ordine dimostrativo 10</Description>

</Order>

</soap:Body>

</soap:Envelope>

Si può notare la struttura di un classico mes-saggio SOAP, costituito dalla Envelope, dal Body e dal contenuto (nel nostro caso l’ordi-ne). A questo punto possiamo creare un og-getto SoapSender, per inviare il messaggio ad un altro EndpointReference (cioè al destina-tario del messaggio):

C#

envelope.Context.Addressing.Action = new Action(“urn:

sendOrder”);

EndpointReference ep = new EndpointReference(

new Uri(“soap.tcp://localhost:34000/DemoReceiver”));

SoapSender sender = new SoapSender(ep);

sender.Send(envelope);

Si vede che dobbiamo per prima cosa crea-re un EndpointReference che rappresenterà il riferimento al servizio da raggiungere, com-presi il protocollo di comunicazione (soap.tcp in questo caso) e la porta di comunicazione ri-servata a questo scambio di messaggi.

Inoltre è di fondamentale importanza l’in-dicazione della Action SOAP del messaggio che stiamo inviando, per consentire al desti-natario di capire cosa gli stiamo chiedendo o dicendo.

La Action, esattamente come tutte le altre meta-informazioni di sicurezza, routing, ecc. si configura attraverso una proprietà specia-le della SoapEnvelope, di nome Context, che rappresenta un riferimento al contesto della singola richiesta o risposta SOAP.

È all’interno di Context che troviamo pro-prietà come Security, Addressing, Attachmen-ts, ecc. che ci permettono di configurare ap-punto il contesto di dialogo SOAP.

SoapReceiverPer ricevere il messaggio appena creato ed

inviato dal SoapSender, dobbiamo dichiara-re una classe derivata da SoapReceiver, della quale dovremo ridefinire il metodo Receive:

.NET

Page 49: v2005 05 vbj65

49N. 65 - Settembre/Ottobre 2005 VBJ

C#

public class DemoReceiver: SoapReceiver

{

protected override void Receive(SoapEnvelope envelope)

{

// Il SoapEnvelope è anche un XMlDocument

// quindi so come cercare e sfogliare

// i nodi al suo interno

envelope.Save(Console.Out);

}

}

In questo esempio ci limitiamo a salvare sul-

la finestra Console del receiver il messaggio

ricevuto dal sender. In condizioni normali do-

vremmo valutare la Action (envelope.Context.

Addressing.Action) e decidere il da farsi. Infi-

ne dobbiamo registrare, lato server, il fatto che

vogliamo stare in ascolto di messaggi SOAP

destinati al nostro SoapReceiver particolare:

C#

public class ReceiverHostCode

{

static void Main()

{

EndpointReference ep = new EndpointReference(

new Uri(“soap.tcp://localhost:34000/DemoReceiver/ “));

SoapReceivers.Add(ep, typeof(DemoReceiver));

Console.ReadLine();

}

}

Come si vede ci appoggiamo alla classe

SoapReceivers che esponde un metodo sta-

tico Add, che ci consente di aggiungere un

Receiver su un determinato EndpointRefe-

rence. Da notare che con un singolo Recei-

ver potremmo stare in ascolto su diversi En-

dpointReference, quindi anche su diversi pro-

tocolli e indirizzi.

Dal momento che il motore di WSE rimane

in ascolto su un thread diverso da quello prin-

cipale della nostra applicazione, dobbiamo so-

spendere il progamma host aspettando la pres-

sione del tasto INVIO a Console. In condizioni

di regime ci converrà realizzare un’applicazio-

ne Windows Forms o ancor meglio un servizio

del sistema operativo, che rimangano in esecu-

zione e quindi in ascolto per i nostri messaggi

SOAP. Il messaggio stampato a Console conter-

rà qualche informazione in più rispetto a quel-

lo salvato in precedenza, principalmente per il

fatto che il messaggio questa volta sarà passato

attraverso il Channel della SoapPort di uscita

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-

te a diversi namespace XML. Si tratta proprio

dei namespace XML che troviamo aggiunti al

messaggio finale.

Rispondere ai messaggiSe volessimo a questo punto rispondere al

sender, dovremmo avere anche dal suo lato un

oggetto derivato da SoapReceiver e posto in

ascolto su un determinato EndpointReferen-

ce. Il sender potrebbe per esempio dire:

C#

envelope.Context.Addressing.ReplyTo = new ReplyTo(new

Uri(“soap.tcp://localhost:35000/Sender”));

per comunicare al receiver l’indirizzo al qua-

le inviare eventuali risposte (ReplyTo).

Il receiver dal canto suo potrebbe risponde-

re chiedendo alla SoapEnvelope di generare

la risposta per il messaggio appena ricevuto,

nel modo seguente:

C#

SoapEnvelope response = new SoapEnvelope();

response.SetBodyObject(orderResponse, “http://

schemas.devleap.com/Response”);

envelope.Context.Addressing.SetResponseHeaders(response.

Context.Addressing);

In pratica dobbiamo creare una nuova Soa-

pEnvelope, inserire al suo interno la risposta

(orderResponse nel nostro esempio) e chiede-

re alla richiesta di configurare l’indirizzamen-

to SOAP della risposta. L’oggetto SoapEnvelo-

pe ricevuto come richiesta compilerà i cam-

pi corretti della risposta, per consentire al de-

.NET

Page 50: v2005 05 vbj65

50 VBJ N. 65 - Settembre/Ottobre 2005

stinatario di capire che il messaggio inviato-

gli costituisce una risposta per il precedente

messaggio. Non ci resterà quindi altro da fare

che inviare la risposta utilizzando una classe

SoapSender, come abbiamo già visto.

L’endpoint che ha originato il dialogo potrà

riconoscere la risposta in base al fatto che

tramite WS-Addressing i messaggi SOAP

possono riportare l’indicazione di un Messa-

geID, che rappresenta univocamente i singo-

li messaggi.

Inoltre esiste una proprietà, sempre di WS-

Addressing, di nome RelatesTo che mette in

relazione tra loro i messaggi.

SoapClient e SoapServiceSe la nostra esigenza è quella di realizza-

re un paradigma di dialogo di tipo richiesta/

risposta, possiamo utilizzare direttamente le

classi SoapClient e SoapService, che altro

non sono che specializzazioni di SoapSender

e SoapReceiver.

In particolare SoapService rappresenta

l’equivalente di un WebService ASMX in WSE

e un SoapClient è ciò che si ottiene costruen-

do una sorta di Web Reference WSE verso un

servizio, anche non necessariamente esposto

con WSE. Partiamo questa volta dall’imple-

mentazione del servizio. Dobbiamo definire

una classe che derivi dalla classe base Soap-

Service e che presenti l’attributo .NET Soap-

Service al posto del classico WebService degli

ASMX. Quindi possiamo decorare i singoli me-

todi del servizio con l’attributo SoapMethod

invece di WebMethod. Ecco un esempio:

C#

[SoapService(“http://schemas.devleap.com/DemoService/”)]

public class DemoService: SoapService

{

[SoapMethod(“urn:SendOrder”)]

public String SendOrder(Order order)

{

return(String.Format(“Ordine {0} ricevuto!”,

order.IdOrder));

}

}

Si noti che l’attributo SoapService riporta il

namespace XML del SOAP Service che stiamo

definendo, mentre l’attributo SoapMethod in-

dica il nome della Action dell’operazione che

descrive.

Mettendo un SoapReceiver in ascolto su un

determinato EndpointReference e protocollo,

per questo servizio, siamo già pronti a riceve-

re richieste a lui destinate.

C#

EndpointReference ep = new EndpointReference(

new Uri(“soap.tcp://localhost:34000/DemoService”));

SoapReceivers.Add(ep, typeof(DemoService));

Qualora volessimo avere un’unica istanza di

servizio in ascolto per tutte le richieste, per

esempio per condividere informazioni di stato,

potremmo assegnare alla classe SoapReceivers

l’EndpointReference unitamente ad una parti-

colare istanza della classe SoapService, invece

che fornire solo il tipo (typeof) generico.

C#

EndpointReference ep = new EndpointReference(

new Uri(“soap.tcp://localhost:34000/DemoService”));

SoapReceivers.Add(ep, new DemoService());

Se avessimo sviluppato un WebService con

dei WebMethod, a questo punto potremmo

chiedere a Visual Studio .NET di creare una

Web Reference verso la URL del servizio. Per

altro Visual Studio .NET, quando creiamo del-

le Web Reference, non fa altro che eseguire lo

stesso codice che potremmo eseguire autono-

mamente chiamando dal prompt dei comandi il

tool WSDL.EXE. Ecco che WSE2 fornisce qual-

cosa di molto simile: WSEWSDL2.EXE. Possia-

mo invocarlo dandogli come argomento la URI

di un servizio, per ottenere in cambio il codice

di un SoapClient pronto da istanziare.

Command Prompt

C:\Program Files\Microsoft WSE\v2.0\Tools\Wsdl\WseWsdl2.exe

URI-Servizio file.cs

.NET

Page 51: v2005 05 vbj65

51N. 65 - Settembre/Ottobre 2005 VBJ

Nel nostro caso avremo:

Command Prompt

WseWsdl2.exe soap.tcp://localhost:34000/DemoService

DemoServiceClient.cs

Ed ecco che verrà auto-generato per noi un file di codice che descriverà la classe Order e il SoapClient del servizio.

Per brevità riporto solo le parti salienti del codice e rimando agli allegati all’articolo per i dettagli:

C#

[SoapService(“http://schemas.devleap.com/DemoService/”)]

public class DemoService : SoapClient

{

public DemoService() : base( new Uri(“soap.tcp:

//localhost:34000/DemoService”) )

{

}

[SoapMethod(“urn:SendOrder”)]

public System.String SendOder( Order request )

{

return (System.String)base.SendRequestResponse(“SendOrder”,

request).GetBodyObject( typeof(System.String), SoapService

Attribute.TargetNamespace);

}

// omissis...

}

Il codice contiene la definizione di una classe di nome DemoService, che deriva da SoapClient ed espone un metodo Sen-dOrder. Si noti che sia la classe che il me-todo sono decorati anche lato client rispetti-vamente dagli attributi SoapService e Soap-Method.

Non entro nel merito dell’implementazione del metodo SendOrder, ma sottolineo soltan-to il fatto che WSEWSDL2.EXE ha generato per noi anche i metodi BeginSendOrder ed EndSendOrder, per consentirci di invocare il SoapService in modo asincrono, lato client [8]. Una nostra applicazione client, che vo-glia utilizzare il SoapService, dovrà limitar-si ad includere o referenziare il codice ap-

pena generato e poi utilizzare la classe De-moService creata:

C#

DemoService svc = new DemoService();

Order order = new Order();

order.IdOrder = 10;

order.Description = “Ordine 10”;

Console.WriteLine(svc.SendOrder(order));

Console.ReadLine();

ConclusioniSpero con questi esempi di aver stimolato la

vostra fantasia e di avervi fatto venire la vo-glia di provare a creare qualche applicazione in grado di comunicare tramite SOAP con al-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 è utilizzabile solo da WSE2 stesso.

Se vogliamo utilizzare WSE per rivolgerci ad altre piattaforme dobbiamo pensarlo solo come estensione di ASP.NET e dei Web Servi-ce ASMX. Ciò nonostante il SOAP Messaging risulta molto comodo in diverse situazioni in cui si vogliono mettere in comunicazione tra loro applicazioni .NET sfruttando le potenzia-lità di SOAP.

Bibliografia[1] P. Pialorsi – “Service Oriented Architecture”,

Visual Basic Journal n° 61[2] P. Pialorsi – “SOA e il .NET Framework”,

Visual Basic Journal n° 62

Riferimenti[3] http://msdn.microsoft.com/webservices/[4] http://www.devleap.com/wse2/ [5] http://www.w3.org/TR/2005/REC-soap12-

mtom-20050125/[6] http://www.devleap.com/SchedaArticolo.a

spx?IdArticolo=10450[7] http://winfx.msdn.microsoft.com/[8] http://www.devleap.com/SchedaArticolo.a

spx?IdArticolo=10610

.NET

Page 52: v2005 05 vbj65

.NET TO OLS

52 VBJ N. 65 - Settembre/Ottobre 2005

DTSBackup 2000di Angelo Ossola

Probabile, anche se poco auspicabile, scenario

aziendale: un sistema basato su Microsoft SQL 2000

esegue trasferimenti ed elaborazioni di dati attra-

verso dei DTS, fondamentali per la realtà produtti-

va, tra piattaforme eterogenee (ad esempio da e ver-

so AS400), magari schedulati automaticamente per

girare in fase notturna. Un “bel” giorno: crash del

server! Si rende necessario rimettere in piedi tut-

to il sistema. Ovviamente, lo spero, nessuno è così

scellerato da non avere backup dei dati periodici e

delle applicazioni fondamentali al buon funziona-

mento dell’ambiente che deve gestire. I backup, se

fatti a regola d’arte, consentono di ripristinare tutti i

database in modo completo e rigoroso ma (c’è sem-

pre un ma …) c’è un problema: i DTS? Non ci sono

nei backup! Sfido chiunque a riscriverli in un mo-

mento del genere senza commettere qualche errore

o dimenticanza. La soluzione veramente facile ed

immediata ce la propone DTSBackup, un tool tanto

semplice da usare quanto efficace rispetto al proble-

ma appena esposto. Av-

viando il programma ed

osservando l’ambiente

di lavoro possiamo im-

mediatamente intuire la

logica davvero “easy” con

la quale è stata svilup-

pata l’applicazione; pre-

mendo il pulsante per la

selezione della sorgente

dei dati ci viene presen-

tata una finestra di dialo-

go che risulterà molto fa-

miliare a tutti gli avvezzi

di Microsoft SQL 2000 e

che permette di selezio-

nare il server (o la named

instance) SQL.

Una volta impostato il server sorgente viene espo-

sto l’elenco di tutti i DTS presenti nella basi di dati

dal quale è possibile selezionare quelli per i quali

si vuole eseguire il backup. A questo punto è ne-

cessario impostare la destinazione del backup ed è

qui che la versatilità del programma balza agli oc-

chi dell’utente: possiamo impostare un altro server

nel quale salvare i DTS (a questo punto possiamo

usare questo tool anche per copiare DTS tra un ser-

ver ed un altro), salvarlo in un file con estensione

.dts, in uno Structured Storage File oppure in un

Meta Data Services Packages. Avviando il trasfe-

rimento dei DTS viene proposto un report di fun-

zionamento in puro stile SQL 2000 nel quale viene

proposto l’esito di ogni operazione eseguita nel job

appena avviato.

Vi sono, inoltre, interessanti opzioni che rendono

questo strumento ancor più elastico e flessibile, tra

cui la possibilità di inserire la password da usare

con package criptati, esportare la lista dei DTS in

formato txt e, ancor più utile in determinate circo-

stanze, la possibilità di “pilotare” il software anche

da riga di comando. Dalla

linea di comando è pos-

sibile impostare i server

sorgente e destinazione,

la modalità di connessio-

ne ai server, username e

password per le varie

connessioni ed altro an-

cora. Da sottolineare, in-

fine, anche la possibili-

tà di criptare anche nel-

la linea di comando sia

lo username che la pas-

sword. Per quanto con-

cerne, invece, l’operazio-

ne di restore essa avviene

in modo del tutto analo-

go, seppur a ruoli ovvia-

Page 53: v2005 05 vbj65

.NET TOOLS

53N. 65 - Settembre/Ottobre 2005 VBJ

mente invertiti, rispetto a quella di backup. Tiran-

do le somme siamo in presenza di un tool, tra l’al-

tro frequentemente aggiornato dai suoi creatori, che

sopperisce ad una mancanza dell’enterprise mana-

ger di SQL 2000 in modo semplice ed efficace.

CodeColorizerdi Angelo Ossola

CodeColorizer, ovvero quando la semplicità è

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-

to usare per risparmiare tempo e per avere un

risultato davvero congruente con la formatta-

zione del codice usata negli ambienti di svilup-

po. Questo tool, free, e scaricabile velocemente

dal sito di riferimento (sono solo circa 50KB) si

presenta con soli due file: l’eseguibile ed una

dll a corredo.

Lanciando il programma siamo accolti in un

ambiente decisamente user-friendly, come si

può vedere dall’immagine, che è essenzialmen-

te composto da quattro pulsanti e da un com-

boBox. Nell’elenco presente è possibile sceglie-

re il linguaggio del file sorgente che andremo

a caricare e per il quale vogliamo sviluppare la

pagina HTML; i linguaggi che vengono gestiti

dal programma sono diversi: C#, VB.NET, VB

Script, Java Script, C++, SQL, Cascading Stye

Sheet, Cobol, Algol e i linguaggi di markup qua-

li ad esempio HTML ed e vari dialetti derivati

dall’XML (XSL, VXML, ecc.).

Una volta scelto il linguaggio con il quale vo-

gliamo operare, passiamo a caricare il file sor-

gente che ci interessa; questo può essere fatto

attraverso il pulsante relativo oppure con un

comodissimo drag&drop in puro stile Windows.

A questo punto il documento viene presentato

nell’area di testo più in alto. Per “colorizzare”

il nostro sorgente è sufficiente cliccare l’omoni-

mo pulsante; il relativo risultato viene presen-

tato, in formato HTML nell’area di testo più in

ProdottoDTSBackup 2000 UI

Url di riferimento http://www.sqldts.com/dtsbackup/

Sta to Release1.1.6

Semplicità d’uso �����L’interfaccia in puro stile Microsoft SQL 2000 permette ai vete-rani di questo ambiente di essere subito a proprio agio con que-sta applicazione.

Utilità �����È un tool che sopperisce ad una insufficienza dell’enterprise ma-nager in modo davvero apprezzabile.

Qualità prodotto ����� Software che implementa ogni sfaccettatura della funzionalità per cui è stato progettato con elevata stabilità ed efficienza.

Qualità documentazione �����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-rimento si possono trovare tutte le informazioni necessarie.

Page 54: v2005 05 vbj65

.NET TOOLS

54 VBJ N. 65 - Settembre/Ottobre 2005

basso. La presenza di queste due aree di testo è veramente comoda per apportare modifiche in corsa al codice sorgente per poi vederle imme-diatamente applicate al codice sviluppato dal programma (sempre dopo essere passati per il tasto “colorize”).

Un’altra comodità offerta dal software è la pos-sibilità di visualizzare un’anteprima del risulta-to ottenuto all’interno di una finestra del nostro browser predefinito. Volendo salvare, infine, il nostro lavoro abbiamo la possibilità di farlo sia in formato HTML che in formato RTF.

Un unico appunto che potrebbe essere mosso all’autore del tool è l’impossibilità di modifica-re l’output prodotto per poter, ad esempio, por-tare piccoli adattamenti al codice ottenuto sen-za doversi affidare ad altri strumenti. Se la se-conda area di testo diventasse un editor HTML, anche semplice, il lavoro sarebbe ulteriormen-te semplificato.

E verrebbe in grande aiuto qualora si avesse la necessità di inserire in una pagina di un sito del codice che possa, però, mantenere la format-tazione originale.

Sul sito del programma, oltre ad altri tool mol-to interessanti per gli sviluppatori, è possibile anche registrarsi ad una mailing list che per-mette di restare sempre informati su eventua-li aggiornamenti.

SharpWebMaildi Raffaele Di Natale

Nel panorama delle WebMail application, ricco nelle soluzioni e nelle tecnologie adottate, Shar-

pWebMail si distingue principalmente per la sem-plicità dell’installazione e della configurazione. Il progetto che sta alle sue spalle è sicuramente de-gno di nota, poiché l’autore ha utilizzato tre mo-duli software, sempre open source, tutti leader nel proprio ambito. Un’interfaccia senza fronzoli e funzionalità base efficienti consentono un fa-cile adattamento alle più comuni configurazioni dei servizi di posta elettronica. Le pagine .ASPX sviluppate in C# richiamano cinque moduli, dei quali i primi tre sono legati direttamente all’ap-plicazione ed i restanti sono di supporto:

� SharpWebMail.dll, il modulo principale;� SharpMimeTools.dll, modulo in versione beta

per il parsing dei messaggi MIME;� SharpWebMail.resources.dll, per le risorse mul-

tilingua;� Log4tNet.dll, modulo per i servizi di login;� OpenSmtp.dll, modulo per i servizi SMTP;� FredCK.FCKeditorV2.dll, modulo dell’html edi-

tor più conosciuto.

L’applicazione si basa sul .Net Framework 1.1 di Microsoft e su Mono 1.0, ma all’interno della directory bin sono presenti i binari per il .Net Framework 2.0 e per e Mono 2.0. Pertanto que-sta web application può girare indistintamente sia su Windows sia sugli altri sistemi suppor-tati da Mono. Per quanto concerne il web può essere utilizzato con gli IIS (Internet Informa-

tion Services) oppure con Apache, ovviamente insieme a Mono se non si tratta di un sistema Windows.

È necessario predisporre l’indirizzo di almeno un server POP3 (o IMAP) e di un server SMTP. SharpWebMail è stato testato con i browser internet più diffusi al momento e vale a dire Internet Explorer 6.0 e FireFox 1.0. L’applica-zione descritta in quest’articolo è stata instal-lata su Windows XP SP2 con gli IIS. SharpWeb-Mail, in versione 0.11 beta, può essere scarica-to gratuitamente: il pacchetto comprende sia i file sorgente che i binari. Dopo aver scaricato il

ProdottoCarlosAg.CodeColorizer

Url di riferimento http://www.carlosag.net/

Sta to Releasev1.0.0.1

Semplicità d’uso �����L’uso di questo tool risulta già dal primo approccio decisamen-te banale.

Utilità �����Permette di realizzare un’operazione, probabilmente tediosa, in un attimo.

Qualità prodotto ����� Realizza un’unica funzionalità ma in modo egregio: massimo risul-tato con il minimo sforzo.

Qualità documentazione �����Considerato l’evidente facilità d’uso non si può certo chiede-re di più.

Page 55: v2005 05 vbj65

.NET TOOLS

55N. 65 - Settembre/Ottobre 2005 VBJ

/>

</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:

l’indirizzo http://localhost/webmail/ pun-

terà direttamente alla pagina login.aspx che mo-

strerà il form di login.

Il titolo della finestra della pagina web può esse-

re personalizzato tramite il campo title della sezio-

ne general cosi come il titolo del form di login me-

diante title della sezione login e la lingua di default

mediante il campo default_lang.

Relativamente al campo username le possibili-

tà sono tre:

� Richiedere l’indirizzo completo, per esempio

[email protected], fissando mode=‘1’;

� Richiedere semplicemente il nome, per esem-

pio raffaele, con mode=‘2’;

� Accodare al nome inserito un’ulteriore stringa

standard per tutti gli utenti, mediante il campo

append. Per esempio se append=“@dominio.it”

e lo username è raffaele allora la stringa finale

sarà [email protected]. In questo caso sarà

però necessario definire il campo mode=‘3’.

Un’applicazione di posta elettronica che si ri-

spetti non può far mancare la rubrica ai propri

utenti: gli indirizzi potrebbero essere collocati in

un file .MDB di Access o più semplicemente ge-

stiti da un servizio LDAP/Active Directory.

Supponiamo di aver predisposto un database

denominato rubrica.mdb, all’interno del quale

file ZIP ed averne estratto il contenuto, si può

procedere all’installazione. Come accennato in

precedenza questa fase è semplicissima ed è

descritta all’interno del file readme.txt presen-

te nella directory doc. Il contenuto della cartel-

la asp.net deve essere spostato all’interno della

cartella di destinazione del server web, configu-

rando in esso la directory Webmail.

A questo punto non resta che personalizzare

l’applicazione in base ai servizi che ci sono mes-

si a disposizione, alla modalità d’accesso pre-

ferita e alla tipologia della rubrica prescelta.

SharpWebMail è una web application ASP.NET

e pertanto la configurazione avviene mediante

il consueto file web.config che si trova sempre

all’interno della cartella WebMail. Per una con-

figurazione minima basta intervenire sulle due

sezioni principali read e send, che si riferisco-

no rispettivamente alle impostazioni dei server

della posta in entrata e in uscita. Di seguito si

propone un esempio per read e per send, da

adattare alle proprie esigenze:

<servers>

<server

name=”Default POP3 Server”

regexp=”*”

protocol=”pop3”

host=”pop3.dominio.it”

port=”110”

Page 56: v2005 05 vbj65

.NET TOOLS

56 VBJ N. 65 - Settembre/Ottobre 2005

abbiamo definito una tabella denominata Ta-

ble1 formata da due colonne nome ed email ri-spettivamente.

Salviamo il file in C:\ e inseriamo una sezione <addressbook> nel file web.config. A seconda della tipologia della rubrica prescelta potrebbe essere necessario impostare la corrispondente sorgente dati ODBC.

<addressbook

Name=”MS Access Address Book”

Type=”odbc”

ConnectionString=”Driver={Microsoft Access Driver(*.mdb)};DBQ=C:

\rubrica.mdb”

SearchString=”SELECT nome, email FROM Table1”

NameColumn=”nome”

EmailColumn=”email”

PageSize=”10”

SearchStringRealName=”SELECT nome, email FROM Tabella1 WHERE

email=’$USERNAME$’”

/>

È possibile inserire anche più di una rubrica.L’applicazione può filtrare i messaggi ricevuti,

eliminando dal contenuto degli stessi sia codi-ce html superfluo sia script potenzialmente pe-ricolosi. Per far questo poniamo il campo sani-

tizer_mode= ‘1’ nella sezione message. Questa funzionalità non è ancora del tutto affidabile. Da notare infine la sezione authentication che con-sente di scegliere tra quattro modalità differen-ti per il login: tramite il form standard dell’ap-plicazione, il form di Windows, quello passport oppure non definirne alcuno.

SharpWebMail si presenta con un’interfaccia ormai standard per questo tipo di applicazioni. Sulla parte alta sono presenti i pulsanti di navi-gazione, di logout e d’aggiornamento; a sinistra si trovano i comandi principali e sulla parte de-stra il form relativo al messaggio in uscita.

Nella parte bassa è visibile la finestra della ru-brica. Intervenendo sul file Sharpwebmail.css è

Page 57: v2005 05 vbj65

.NET TOOLS

57N. 65 - Settembre/Ottobre 2005 VBJ

possibile definire stili differenti per l’applicazio-

ne. Da quanto emerso appare evidente che si trat-

ta di un programma semplice e ben congegnato.

Un aspetto migliorabile, anche se secondario, è il

numero delle funzionalità a disposizione.

ZanebugLo Unit Testing visuale

di Fabio Perrone

Per “Unit Testing” s’intende l’effettuazione di

verifiche funzionali e d’affidabilità riguardan-

ti il comportamento di determinati componenti

rispetto al soddisfacimento di requisiti defini-

ti in fase di progettazione. Nello sviluppo di un

progetto software, lo Unit Testing sta assumen-

do un ruolo sempre più preponderante, senza

dubbio anche perché rappresenta una “pietra

miliare” dell’Extreme Programming o XP. Gli

unit test sono scritti all’interno del codice che

deve essere testato.

Come si può quindi dedurre, la scrittura di test

per progetti particolarmente complessi può esse-

re un’operazione particolarmente lunga e labo-

riosa. Per semplificare la creazione e la gestio-

ne dei test, esistono i cosiddetti “Unit Testing

framework”, che aiutano a scrivere codice, ad

effettuare il debug del codice e ad integrare nel

miglior modo possibile i test all’interno del co-

dice. Uno dei migliori “Unit Testing framework”

per Microsoft .NET è senza dubbio NUnit [1],

che permette di segnare il codice con attribu-

ti per indicare quali metodi devono essere ese-

guiti quando un test ha successo.

Per chi avesse già utilizzato altri framework,

la seguente nomenclatura potrebbe essere fami-

liare, anche se è bene avere sempre chiare in

mente le definizioni di Test, che è un metodo

che esegue delle convalide interne e può avere

esito positivo o negativo; TestFixture, che è una

classe che contiene più metodi di test; TestAs-

Page 58: v2005 05 vbj65

.NET TOOLS

58 VBJ N. 65 - Settembre/Ottobre 2005

sembly, che è una collezione di TestFixture in

un assembly; TestSuite, che è una collezione di

TestAssembly costruita dinamicamente da Za-

nebug per ogni assembly che viene caricato al-

l’interno del programma. Prima di analizzare le

notevoli possibilità offerte dalla parte grafica di

Zanebug, vediamo come scrivere test all’inter-

no del codice che possano poi essere elaborati

ed analizzati dal nostro software.

Il primo passo consiste nel mettere un riferi-

mento alla dll che costituisce il motore di Za-

nebug: Adapdev.UnitTest.dll, quindi importia-

mo il namespace Adapdev.UnitTest all’interno

del nostro codice; così facendo siamo in grado

di utilizzare tutti gli attributi messi a disposi-

zione da Zanebug per identificare una classe

come classe di test (attributo TestFixture) e un

metodo come metodo di test (attributo Test).

Portando a termine questi semplici passi, ab-

biamo già creato la base per l’effettuazione di

qualsiasi unit test a cui vogliamo sottoporre il

nostro codice.

Quando si esegue il testing “a mano” senza

usare alcun framework, assumono una notevo-

le importanza le asserzioni, caratteristica che si

riflette in maniera più avanzata anche in Zane-

bug tramite la classe Assert, che prevede meto-

di per controllare se due oggetti sono uguali, se

due oggetti hanno lo stesso riferimento (in poche

parole se puntano allo stesso oggetto), se una

determinata condizione è falsa e altre interes-

santi opzioni ben documentate nella guida.

Oltre a questi fondamentali attributi che forni-

scono l’ossatura per approntare un buon test, è

possibile inserire una descrizione per ogni test

che si compie, la categoria che si vuole fare ap-

partenere un determinato test, se da un deter-

minato metodo ci si aspetta una ben specifi-

ca eccezione, oppure se un metodo deve essere

ignorato in fase d’esecuzione.

Dopo aver brevemente esaminato le istruzioni

che devono essere inserite nel codice per poter

effettuare i test, passiamo ora all’analisi dell’in-

terfaccia utente di Zanebug, che senza dubbio

rappresenta l’aspetto più interessante e più po-

tente di tutto il tool.

La parte principale dell’interfaccia utente del

programma è occupata dalla cosiddetta Test Bar,

che permette di eseguire o interrompere i test,

mostrare la percentuale d’elaborazione dei test

correnti e, a test ultimato, individuare grafica-

mente la percentuale di test che hanno avuto

successo, il tutto evidenziato dalla colorazione

differente in base all’esito dei test: ovviamente

rosso se uno o più test non ha avuto esito posi-

tivo, verde altrimenti.

Il TreeView presente nella schermata princi-

pale elenca la struttura ad albero dei Test, Te-

stFixture, TestAssembly e TestSuite, permet-

tendo di selezionare o meno un test per la sua

eventuale esecuzione. Selezionando una qual-

siasi voce del TreeView vengono evidenziate tut-

te le caratteristiche del test che si possono im-

mettere in fase di scrittura all’interno del co-

dice, già menzionate in precedenza (categoria,

descrizione, ecc.).

D’assoluto interesse sono i numerosi Tab pre-

senti nell’interfaccia principale che permetto-

no di filtrare in numerosi modi i test: tutti, solo

quelli che hanno avuto esito positivo, solo quel-

li negativi oppure quelli ignorati.

Per ognuno di questi tab vengono illustrati

una notevole mole di dati, quali il tipo di test,

il messaggio di un’eventuale eccezione genera-

ta, il tempo medio d’esecuzione del test, la du-

rata in percentuale del test rispetto al TestSui-

te, la quantità di memoria consumata dal test,

il numero d’iterazioni del test.

Oltre a queste caratteristiche, il menu conte-

stuale d’ogni tab prevede ulteriori interessanti

analisi grafiche, come il confronto tra più test

o la media di un test evidenziato rispetto alla

media totale. Oltre a tutto ciò, il tab “Perfmon”,

come suggerisce il nome, offre un Performance

Monitor per tener traccia di statistiche presta-

zionali senza dover lasciare l’ambiente di Za-

nebug ricorrendo magari ad altri strumenti o al

Performance Monitor nativo di Windows.

Due ulteriori caratteristiche rendono il pro-

dotto completo sotto ogni punto di vista: la

console di Zanebug e l’integrazione con Visual

Studio.NET.

La prima permette l’esecuzione dei test da riga

di comando con una gamma di scelte molto am-

pia, simile a quella della parte grafica (escluse

le statistiche avanzate e i grafici, ovviamente),

Page 59: v2005 05 vbj65

59

.NET TOOLS

N. 65 - Settembre/Ottobre 2005 VBJ

ProdottoZanebug

Url di riferimento http://www.adapdev.com

Sta to ReleaseStabile (versione corrente 1.5.0.1)

Semplicità d’uso �����La semplice ma funzionale interfaccia grafica facilita molto.

Utilità �����Per chi utilizza lo Unit Testing è uno strumento fondamentale per semplificare la creazione e l’utilizzo di test visuali.

Qualità prodotto ����� Affidabile, nei test sul prodotto eseguiti non ha mai mostrato par-ticolari problemi.

Qualità documentazione �����Presenti sia help on line che documentazione su Web.

permettendo così di utilizzare la modalità batch;

la seconda installa un add-in nell’IDE di Visual

Studio.NET (solo versione 2003, per ora), che in-

serisce una voce al menu di contesto utile per

aggiungere in modo rapido gli attributi necessa-

ri in quel punto attivo del codice sorgente, non-

ché una Toolbar per poter eseguire i test diret-

tamente all’interno di Visual Studio.Net.

La versione attuale, la 1.5.0.1, scaricabile gra-

tuitamente, fornisce, come si è potuto dedurre,

buone funzionalità per l’automazione dei test,

oltre ad una dettagliata analisi dei risultati con-

seguiti. Oltre ad essere completamente gratui-

to, è anche possibile effettuare il download del

codice sorgente, caratteristica che per i più vo-

lenterosi rende ancora più appetibile quest’ot-

timo strumento.

Page 60: v2005 05 vbj65

60 VBJ N. 65 - Settembre/Ottobre 2005

I design pattern

più famosi implementati

in VB.NET

di Lorenzo Vandoni

Ipattern descritti nel libro “Design Pattern” di

Gamma, Helm, Johnson e Vlissides sono or-

ganizzati in tre categorie: pattern di creazio-

ne, di comportamento e strutturali.

Nelle due puntate precedenti abbiamo esaminato

due tra i più noti pattern di comportamento, Itera-

tor e Observer, e un pattern di creazione, Factory

Method. Concludiamo questa piccola serie mostran-

do un pattern strutturale, Adapter.

Il pattern Adapter, descrizioneCome al solito, la descrizione del pattern verrà

suddivisa in tre sezioni.

In questa prima sezione ne verranno discussi sco-

po, motivazioni e applicabilità.

• Intent. Lo scopo del pattern è quello di per-

mettere ad una classe A di utilizzare i servizi

di una classe B, nell’ipotesi che B implementi

le funzionalità desiderate, ma fornisca un’in-

terfaccia pubblica incompatibile con quella ri-

chiesta da B.

• Motivation. A volte può capi-

tare che un’applicazione che

si sta sviluppando richieda da

parte di alcune classi un’in-

terfaccia ben precisa. Questo

capita soprattutto durante le

operazioni di manutenzione,

quando cioè un’applicazione

viene modificata per rispon-

dere a nuove esigenze.

Per esempio, potrebbe capita-

re che le funzionalità di log di

un programma, inizialmente

dirette verso un normale file

di testo, debbano in un secon-

do tempo essere convertite in

modo da memorizzare le righe

di log in una tabella di databa-

se. In questi casi, si può veri-

ficare la necessità di sfruttare

delle classi di libreria che of-

frono le funzionalità deside-

rate, ma tramite un’interfac-

cia di programmazione diver-

sa da quella richiesta dall’ap-

plicazione. Le alternative sono

tre: o si modificano le classi di

libreria, o si modifica il codice

dell’applicazione, o si crea un

adattatore che funga da trami-

DP 4

Il pattern Adapter suggerisce come modificare una classe

server in modo da adattarsi all’interfaccia richiesta da

altre classi client

Quarta puntata

Lorenzo Vandoni è laureato in Informatica, ed è uno spe-

cialista di progettazione e sviluppo con tecniche e linguaggi

object-oriented. Ha collaborato alla realizzazione di framework,

strumenti di sviluppo e software commerciali in C++, Java e

Visual Basic. Può essere contattato tramite e-mail all’indirizzo

[email protected].

SOFTWARE ENGINEERING

Page 61: v2005 05 vbj65

61N. 65 - Settembre/Ottobre 2005 VBJ

teServer, sfruttando però un’interfac-

cia diversa. Il fatto che il programma

client sia rappresentato tramite una sola

classe è ovviamente una semplificazio-

ne, che però non modifica la struttura

della soluzione.

° ServerInterface rappresenta l’interfac-

cia che l’applicazione client intende uti-

lizzare. A seconda dei casi, si potrà trat-

tare di una vera interfaccia, di una clas-

se base, oppure di un insieme di classi

ed interfacce. In pratica, ServerInter-

face rappresenta l’insieme di funzioni

utilizzate dalla classe Client.

° ConcreteServer identifica la classe, che

si suppone già presente e implementa-

ta all’interno di un’altra applicazione, di

un toolkit o di una libreria, che forni-

sce le funzionalità desiderate, ma che si

rende accessibile tramite un’interfaccia

di programmazione (cioè un insieme di

proprietà e funzioni) diversa e non com-

patibile da ServerInterface.

° Adapter è la classe che fornisce il lega-

me tra Client e ConcreteServer. Questa

classe implementa l’interfaccia Serve-

rInterface, ovvero presenta l’insieme di

proprietà e funzioni che il programma

client si aspetta di usare, e ne delega

l’esecuzione al ConcreteServer.

Sono due i modi con cui questa delega

te. Il pattern Adapter suggerisce appunto la

creazione di un adattatore.

• Applicabilità. Il pattern è applicabile ogni

volta in cui sia impossibile o non conve-

niente modificare sia il codice client sia

il codice server, e sia necessario accedere

alle funzionalità di una classe utilizzando

un’interfaccia di programmazione diversa

da quella fornita dal codice server.

Soluzione del problemaPer questo problema il pattern suggeri-

sce due diverse soluzioni. La prima utilizza

l’ereditarietà, la seconda l’incapsulamento. La

struttura delle classi, nei due casi, è mostrata

nelle Figure 1 e 2.

• Structure. Le due figure sono molto simi-

li. L’unica differenza è data dalla relazione

tra le classi Adapter e ConcreteServer. Nel

primo caso abbiamo una relazione di ere-

ditarietà, mentre nel secondo caso l’Adap-

ter incapsula il ConcreteServer per forni-

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

necessità di sfruttare

i servizi del Concre-

Fi gu ra 1 Una possibile soluzione del pattern Adapter

SOFTWARE ENGINEERING

A volte può capitare che

un’applicazione richieda

da parte di alcune classi

un’interfaccia ben precisa

Page 62: v2005 05 vbj65

62 VBJ N. 65 - Settembre/Ottobre 2005

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.

La prima tecnica è ap-

plicabile solo in C++,

unico linguaggio che

fornisce la possibilità di ereditare il com-

portamento di una classe senza ereditar-

ne l’interfaccia, nonché unico linguaggio

che supporta l’ereditarietà multipla (ne-

cessaria nel caso in cui ServerInterface

sia una classe base). Per questo motivo,

nell’implementazione di esempio verrà

utilizzata la seconda tecnica.

• Collaborations. La struttura dinamica di

questo pattern non ha nulla di particolare.

La classe Client istanzia un Adapter trami-

te l’interfaccia ServerInterface. L’Adapter, a

sua volta, crea un istanza di ConcreteSer-

ver. Tutte le successive chiamate da parte

di Client a metodi implementati dall’Adap-

ter verranno da questo convertiti in chiama-

te al ConcreteServer.

Conseguenze e beneficiVediamo ora quali siano i punti di forza del

pattern ed alcune applicazioni pratiche:

• Consequences. La conseguenza principale

derivante dall’utilizzo di Adapter risiede nel

fatto che esso permette di non modificare né

l’applicazione client, né il codice del server,

normalmente incluso in una libreria, con-

sentendo però all’applicazione di sfruttare

le funzionalità di quest’ultimo.

• Known uses. La maggior parte dei casi pra-

tici in cui questo pattern si rende utile na-

scono nel contesto di operazioni di ristrut-

turazione di vecchie applicazioni per in-

corporare nuove funzionalità. Esempi noti

di applicazione di Adapter possono esse-

re considerati i due assembly che consen-

tono di sfruttare all’interno di applicazio-

ni .NET i vecchi provider OLEDB e i vec-

chissimi driver ODBC.

Questi assembly implementano un’inter-

faccia ben specifica, costituita dalle varie

interfacce definite in System.Data, come

IDBConnection e IDBCommand, ma de-

legano l’esecuzione delle varie funzioni ai

provider e ai driver sottostanti.

Implementazione del patternin VB.NET

Come esempio di implementazione conside-

riamo un’applicazione VB.NET al cui interno

sia stato implementato un meccanismo di log

“artigianale”, e supponiamo che si voglia so-

stituire in un secondo tempo questo mecca-

nismo con qualcosa di più evoluto, costituito

nell’esempio dall’utilizzo della classe Trace

del namespace System.Diagnostics.

L’esempio è costituito da una form, nel cui

evento Form_Load è stato introdotto un er-

rore. L’errore viene gestito all’interno di un

blocco Try Catch con una chiamata al meto-

do Trace dell’interfaccia GenericLogger. L’im-

plementazione “artigianale” prevede che il

GenericLogger sia implementato da una clas-

se DummyLogger, che si limita a visualiz-

zare il messaggio di trace all’interno di un

message box. Il pattern Adapter è costituito

SOFTWARE ENGINEERING

Fi gu ra 2 Una soluzione alternativa per il pattern Adapter

Page 63: v2005 05 vbj65

63N. 65 - Settembre/Ottobre 2005 VBJ

dalla classe LoggerAdapter, che implementa

l’interfaccia GenericLogger in modo differen-

te, delegando l’esecuzione del log alla classe

System.Diagnostic.Trace.

Questa classe del framework implementa le

funzioni di trace informando dei listener che

si possono registrare richiamando il metodo

SOFTWARE ENGINEERING

Listeners.Add. Nell’esempio come listener vie-

ne utilizzata un’istanza della classe TextWri-

terTraceListener, che scrive il messaggio di

trace sulla console.

ConclusioniAdapter è un pattern che risulta utile soprat-

tutto durante la manutenzione o la ristruttu-

razione di applicazioni e librerie, in quanto

consente di sfruttare nuove funzionalità sen-

za modificare in modo sensibile il codice ori-

ginale dell’applicazione.

Perché il pattern possa essere sfruttato, però,

è necessario che l’applicazione sia stata ori-

ginariamente progettata in modo corretto ed

estendibile, incapsulando bene i vari moduli

e le loro interfacce.

Il pattern è applicabile ogni

volta in cui sia impossibile

modificare il codice client e

il codice server

Page 64: v2005 05 vbj65

VBJ 65

IN OFFERTA VBJ 65

Scrivi a

[email protected]

specificando

nell’oggetto della

e-mail:

IN OFFERTAVBJ n. 65

OPPURE

inviaci il coupon

sottostante

al numero di fax

0587/732232

Potrai acquistare

i libri qui riportati con

uno

SCONTOECCEZIONALE

del 10% anche se

acquisti solo un libro

OPPURE

del 20% se acquisti

3 libri

Java and SOAPdi R. Englander

O’ReillyISBN 0596001754

276 pp - 41,40 €

Starting Outwith Visual Basic.Net

di T. Gaddis et al.

Addison WesleyISBN 1576760944890 pp - 62,70 €

Programming Windows Presentation Foundation

di C. Sells - I. Griffiths

O’ ReillyISBN 0596101139447 pp - 39,95 €

Web ServicesPlatform Architecture

AA. VV.

Prentice HallISBN 0131488740456 pp - 46,95 €

Microsoft SQL Server 2005.Changing the Paradigm

SamsISBN 0672327783504 pp - 34,70 €

Head FirstDesign Patterns

di Eric Freeman et al.

O’ReillyISBN 0596007124688 pp - 44,95 €

Page 65: v2005 05 vbj65

65

L I B R I

N. 65 - Settembre/Ottobre 2005 VBJ

Obiettivo di questo libro è guidare il lettore attraverso la progetta-zione e l’implementazione di un compilatore per un linguaggio compatibile con lo storico QuickBasic, interamente realizzato

in Visual Basic .NET e in grado di produrre codice assembly per la piattaforma .NET. Dopo un piacevole excursus storico sui compilatori e, più in particolare, del linguaggio BASIC, il testo presenta una breve introduzione al freamework .NET. Non si tratta della solita presentazione dell’ambiente, ma di una analisi ragionata dei componenti fondamentali (CTS, CLS e CLR) con l’obiettivo di scrivere un compilatore per esso. L’autore illustra i concetti base della teoria dei compilatori e una analisi sintattica del linguaggio QuickBasic, cui segue lo sviluppo dei primi componenti del quickBasicEngine vero e proprio. Dopo aver disegnato la modellazione ad oggetti del linguaggio in uso, vengono discussi nel dettaglio il modulo parser e il generatore di codice. Il lettore è guidato attentamente sia sugli aspetti teorici (espressioni regolari, BNF…) che in quelli pratici (ottimizzazione del codice). Tutto il sorgente dell’ambiente presentato nel libro è disponibile online (evitando, dunque, di appesan-tire inutilmente il volume); al fine di avere una lettura proficua del testo, è consigliabile avere il codice a disposizione sul proprio PC e seguire dettagliatamente i passi indicati dall’autore. Lo studio del compilatore prosegue con una breve analisi del funzionamento di assembler e interpreti e delle implicazioni nello sviluppo dell’applicazione. Prima di concludere, l’autore si sofferma su alcune problematiche legate alla scelta del linguaggio che si intende supportare. Il tema trattato è estremamente particolare, destinato a un pubblico specialistico. Se ne sconsiglia una lettura “casuale”, distratta o saltuaria! Gli studenti potranno trovarci spunti interessanti per comprendere il funzionamento dei compilatori o cimentarsi nella progettazione di un linguaggio.

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), sicuramente consigliato come testo didattico di riferimento.

ControLa scelta di VB.NET per l’implementazione del compilatore è discu-

tibile; probabilmente sarebbe stato più interessante vederne una in C# (a questo proposito l’autore sottolinea che tutti i programmatori C# conoscono VB.NET, ma non è vero il viceversa...).

Stefano Sanna

Build Your Own .NETLanguage and Compiler Autore Edward G. Nilges Editore Apress ISBN 1590901348 Lingua Inglese Anno 2004 Pagine 388 Prezzo € 50,50

Trovare in un titolo di libro le parole “SQL Server” e “Perl” può suscitare qualche perplessità. In effetti, uno dei punti di forza di questo libro consiste proprio nel mostrare a chi usa un

ambiente Microsoft che possono esserci dei casi in cui può valere la pena di usare altri prodotti, come appunto Perl, per semplificare i compiti di amministrazione. Si può anche aggiungere che il fatto stesso di rendere nota l’esistenza di Activestate Perl è un bonus di per sé!

Purtroppo questo pregio diventa anche la maggiore limitazione del libro. Chi è un esperto amministratore di SQL Server ma non conosce nulla di Perl viene guidato passo passo alla comprensione di concetti astrusi quali le pattern e le espressioni regolari, o a leggere un file di configurazione; viceversa, chi proviene da un ambiente Unix e sperasse di comprendere meglio il funzionamento pratico di SQL Server si trova a disagio, quasi come fosse capitato in un mondo alla rovescia. Gli algoritmi e le procedure presentati nel libro sono inoltre molto specializzati, e quindi non particolarmente utili per chi volesse usare ad esempio MySQL come database; insomma non lo si può definire certo un libro per tutte le stagioni.

Occorre però riconoscere che se si fa parte del target cui il libro è dedicato, il suo valore si nota subito. Infatti i vari problemi scelti sono indubbiamente quelli che possono capitare nella vita di chi gestisce basi di dati; inoltre la spiegazione di contorno alla solu-zione è sempre molto dettagliata, e cerca di spiegare anche cosa ci sta sotto, senza limitarsi a porgere la risposta. Risulta più facile quindi adattare gli esempi al proprio caso particolare. Fortunata-mente presso il sito dell’editore è possibile scaricare una versione elettronica di tutti gli esempi, a partire da http://www.apress.com/book/bookDisplay.html?bID=171.In definitiva, un libro per una fascia selezionata di lettori che però lo troveranno di grande utilità.

Pro

Le spiegazioni sono non solo dettagliate, ma danno anche un’idea di cosa c’è dietro alla soluzione proposta.

ControIl libro è davvero utile solo per chi deve amministrare sistemi

SQL Server.

Maurizio Codogno

Real World SQLAdministration with Perl Autore Linchi Shea Editore Apress ISBN 159059097X Lingua Inglese Anno 2003 Pagine 798 Prezzo € 64,15

Page 66: v2005 05 vbj65
Page 67: v2005 05 vbj65
Page 68: v2005 05 vbj65