it
n. 64 - luglio/agosto 2005
bimestrale - anno undicesimo
Direttore Responsabile
Marialetizia Mari (mmari@infomedia.it)
Direttore Esecutivo
upgrade
Renzo Boni (rboni@infomedia.it)
Collaboratori
Andrea Benedetti
Filippo Bonanni
Stefano Corti
0587/732232
John Wiley Potrai acquistare O’Reilly
ISBN 0764595636 ISBN 0596007124
456 pp - 45,80 €
i libri qui riportati con 688 pp - 44,95 €
uno
SCONTO
Design Patterns
ECCEZIONALE C# Essentials
del 10% anche se
di E. Gamma - R. Helm - di B. Albahari et al.
R. Johnson - J. Vlissides
acquisti solo un
libro
Addison Wesley Italia O’ Reilly
ISBN 887192150X OPPURE ISBN 0596003153
414 pp - 39,00 € 216 pp - 24,95 €
del 20% se acquisti
3 libri
VBJ 64
SOMMARIO
L U G L I O / A G O S T O
N.64
SPECIALE
VB.NET
Le novità VB nel nuovo Visual Studio 19
La nuova versione di Visual Studio porta con sé diverse interessanti novità relative al linguaggio Visual Basic.
di Lorenzo Vandoni
DATABASE
SQL Server 2005 ed il CLR: un matrimonio annunciato 29
SQL Server 2005 rappresenta una grande evoluzione nella gestione di database. Vediamo come l’integrazione con il fra-
mework .NET possa migliorare la vita degli sviluppatori e dei DBA.
di Andrea Benedetti
SOFTWARE ENGINEERING
I design pattern più famosi implementati in VB.NET (terza puntata) 39
Il pattern Factory Method consente di delegare a una sottoclasse la scelta di quale oggetto istanziare.
di Lorenzo Vandoni
Editoriale 4
.NET Tools 61
a cura di Davide Mauri
TECNICHE
Verificare la disponibilità di un control OCX con VB6 42
A volte è necessario che un programma si comporti in modo diverso a seconda della disponibilità di un determinato control OCX.
di Lorenzo Vandoni
APPLICATIVI
Controllo Remoto in Visual Basic .NET (prima puntata) 44
di Stefano Corti
I MITI
XML Class Generator 52
Come utilizzare il potente motore di scripting di Windows per produrre ed istanziare classi COM completamente costruite
a runtime, per usufruire di tante interessanti potenzialità.
di Vito Vessia
Codice allegato
All’indirizzo ftp.infomedia.it/pub/VBJ sono liberamente scaricabili tutti i listati relativi agli articoli pubblicati.
La presenza di questa immagine indica l’ulteriore disponibilità, allo stesso indirizzo, di un progetto software
relativo all’articolo in cui l’immagine è inserita. Il nome identifica la cartella sul sito ftp.
Performance
di Andrea Ferendeles
I
l tema delle performance in un’applicazione Un aspetto che mi è rima-
ASP.NET è sempre stato un tema caldo, non tan- sto sempre oscuro e/o difficile
to per un’effettiva mancanza di prestazioni da par- da digerire e da capire è il “pri-
te del .NET Framework, quanto invece per la ric- mo avvio” di una applicazione
chezza dei tool messi a disposizione nell’SDK del ASP.NET.
framework stesso. In ufficio ho provato per gioco a
In particolar modo il tool ngen.exe, presen- fare una serie di interviste ai miei
te nel SDK, è stato sempre oggetto di dispu- colleghi di lavoro, ascoltando le
te e discussioni a me personalmente mai trop- loro reazioni al “primo avvio” di
po chiare e soprattutto di difficile verificabilità. una applicazione ASP.NET.
Vi siete mai chiesti perché il “primo avvio” di una ap- Ecco alcune reazioni: “lento”,
plicazione ASP.NET impiega più tempo dei successi- “lentissimo”, “ma che sta facen-
vi? Cosa succede dietro le quinte? do …”, “sul mio PC non è così
Scopo di questo articolo è quello di indagare, at- lento” (sviluppatore junior), “ba-
traverso semplici test ed osservazioni, nelle directory sta … vado a casa” (aficiona-
Temporary ASP.NET Files, con un’attenzione parti- do ASP).
colare ai tempi di risposta ed alla concomitanza di Quindi ho chiesto loro cosa si
altri fattori quali la GAC (Global Assembly Cache). poteva fare per migliorare i tempi
di risposta del primo avvio (stes-
Premessa so ordine di cui sopra):
“niente”, “assolutamente nien-
Quando nell’ormai lontano 2002 fu rilasciato per la te”, “proviamo sul mio PC”, “fac-
prima volta ASP.NET, una delle feature che colpì tut- ciamola in ASP … però a casa
ti noi, poveri sviluppatori ASP ☺, fu proprio la capa- mia”. Ovviamente sto scherzan-
cità di una applicazione ASP.NET di essere compila- do, però una cosa ho deciso di
ta, anziché interpretata da IIS. Col passare del tem- farla; mi sono rimboccato le ma-
po ci siamo abituati a questa feature e ci siamo spin- niche (alla Peter Norton), mi sono
ti sempre più alla ricerca delle migliori performance armato di “cacciavite” e di “cro-
possibili in applicazioni Web. nometro” ed ho deciso, in prima
persona, di testare e capire il “pri-
mo avvio”: i risultati sono stupe-
facenti!
Andrea Ferendeles ha iniziato ad appassionarsi di informatica
dai tempi del VIC20. Ha sviluppato in BASIC, Logo, Turbo
Pascal, C, C++, Visual Basic, fino ad arrivare ai linguaggi
GAC
.NET, quali VB.NET e C#. È certificato MCP, MCAD, MSF,
MCSD (.NET), MCDBA, MCT. Può essere contattato via email: Facciamo una breve pre-
aferendeles@infomedia.it. messa su GAC, ngen.exe e
Quando la culture non è indicata è per default sembly che risiedono in GAC, in quanto que-
neutral. sti sono Strong Named e dunque già univoca-
mente identificabili. Inoltre gli assembly in GAC,
Per finire ecco invece come registrare il nostro a fronte di una chiamata, non devono essere
assembly – supponiamo MyAssembly.dll – nel- portati, cioè copiati, nella directory dell’assem-
la GAC attraverso il tool gacutil.exe sempre del bly chiamante ma possono restare tranquilla-
.NET Framework SDK. mente lì dove sono; sono appunto condivisi.
Quest’ultimo punto sarà proprio uno degli ele-
Prompt MS-DOS di Visual Studio .NET menti chiave, che rendono la GAC ed il mec-
C:\>gacutil.exe /i MyAssembly.dll canismo di condivisione degli assembly tramite
codebase, due meccanismi privilegiati dal pun-
Ovviamente abbiamo detto che la registra- to di vista delle performance di start-up. Per il
zione in GAC può essere effettuata più sem- momento fermiamoci qui e passiamo ad ana-
plicemente facendo drag&drop dell’assembly lizzare un altro tool fondamentale per le nostre
MyAssembly.dll nella directory c:\windows\ prove: ngen.exe.
assembly.
Osserviamo inoltre che dalla esplorazione (tra- NGEN
mite explorer.exe di Windows) della directory
c:\windows\assembly ci si accorge che questa Dato che nel .NET framework è previsto que-
non sembra essere una vera e propria “folder” sto meccanismo di compilazione Just-In-Time,
del file system che contiene file (provate a fare si è pensato bene di inserire nell’SDK una utility
click con il tasto destro del mouse su un file di pre-compilazione in codice nativo allo scopo
qualunque, non ci sono i classici comandi co- di migliore le performance di “primo avvio” (le
pia, taglia, incolla, ecc… del menu contestuale). richieste successive abbiamo detto infatti “pe-
Infatti quando installiamo il .NET Framework vie- scherebbero” dalla RAM).
ne applicata una patch ad explorer.exe per dare Il tool in questione si chiama ngen.exe; vedia-
un nuovo aspetto alla cartella Assembly ed at- mo un esempio di generazione di immagine na-
tribuire un diverso significato al drag&drop qui tiva, sempre con il nostro assembly esemplifi-
operato (registrazione appunto e non copia ed cativo MyAssembly.dll.
incolla). Proviamo ora invece a curiosare con il
prompt MS-DOS proprio nella cartella in que- Prompt MS-DOS di Visual Studio .NET
stione. Come si vede dalla Figura 1 in realtà C:\>ngen.exe MyAssembly.dll
la struttura del file system per questa cartella
è nascosta e ben diversa.
Proprio nella sotto-directory
GAC troveremo diverse altre
cartelle – una per ogni assem-
bly presente in GAC – ed alla fine
della struttura, una copia origina-
le in IL (Intermediate Language
generato da uno dei compilato-
ri .NET) dell’assembly registrato
in GAC. Quando da una applica-
zione ASP.NET, il code-behind ri-
chiede i servizi di un assembly,
questo deve essere innanzitutto
individuato e solo dopo una se-
rie di procedimenti che portano
alla sua individuazione univoca,
esso viene compilato just-in-time
e quindi portato in RAM. Questo
meccanismo di identificazione è Figura 2 Alcuni file sono identificati come "Native Images"
estremamente più facile e dun-
que più veloce per tutti gli as-
Ovviamente questo meccanismo non rispecchia Supponendo di aver compilato tutte e 100
assolutamente la realtà e non vuole essere nem- le classi e di aver aggiunto un riferimento al-
meno la base di partenza per un benchmark; l’assembly Class100.dll nella nostra applica-
vuole invece portare all’esasperazione i mecca- zione ASP.NET, che d’ora in avanti chiame-
nismi di JITting e pre-compilazione nella Tempo- remo per comodità WebGenerate, vediamo i
rary ASP.NET Files proprio per rendere evidenti differenti scenari in cui fare i test e per i quali
le differenze nei tempi di risposta e consentirne sarà interessante osservare in termini di tem-
dunque una facile valutazione. po quanti millisecondi trascorrono prima di
Tutte e 100 le classi sono dotate dell’attribu- vedere la stringa “something” apparire nella
to AssemblyKeyFile in modo da rendere tutti e nostra TextBox.
100 gli assembly generati (uno per ogni classe,
Class1.dll, Class2.dll, … Class100.dll) Strong Na- Scenario 1 - “No Gac, No Native Images”
med e pronti dunque ad essere registrati all’oc- Nel primo scenario non metteremo nulla in
correnza dei nostri test, in GAC. Inoltre, tutte le GAC e non genereremo alcuna immagine nati-
chiamate si riducono alla fine alla restituzione di va. Insomma la situazione tipica di una applica-
una stringa “something” (che vedremo apparire zione ASP.NET con esecuzione side-by-side.
sul controllo textbox della nostra WebForm1.aspx Effettueremo in questo scenario, così come
al termine del caricamento della pagina stessa. nei successivi, un totale di tre 3 prove.
Nel codice allegato all’articolo troverete una uti-
lity per generare il sorgente di queste classi, per Scenario 1 - Prova 1
generare una serie di file batch (.bat) per com- “First Execution, No Gac, No Native Ima-
pilarle, per pubblicare/rimuoverle dalla GAC e ges, No Temporary ASP.NET Files”
per creare/eliminare le relative immagini native Per questa prima prova, ci dovremo as-
con ngen.exe. sicurare che la directory C:\WINDOWS\
La serie di chiamate in cascata alle 100 classi Microsoft.NET\Framework\v1.1.4322\
ci assicurerà, per quanto concerne i nostri test, Temporary ASP.NET Files sia vuota (elimi-
che il JIT “attraversi” tutte le classi e quindi tutti natene tranquillamente tutto il contenuto ma
gli assembly, senza escluderne nemmeno una e NON la cartella stessa e solo dopo aver riav-
ci darà modo di rendere “evidenti”, in termini di viato IIS – iisreset.exe) quindi riavviamo il ser-
tempo trascorso, le differenti strategie adottate vizio IIS, proprio per simulare il nostro ormai
nei diversi scenari. famigerato “primo avvio”. Se ora tentassimo
di accedere tramite browser alla
nostra WebForm1.aspx avrem-
mo un risultato logicamente non
corretto, in quanto il riavvio di
IIS non rimette automatica-
mente in esecuzione il proces-
so w3wp.exe.
Teniamo dunque in considera-
zione questo aspetto e superia-
molo con un piccolo stratagem-
ma. Creiamo un’ulteriore e ba-
nale applicazione ASP.NET che
faccia da “gateway” al solo sco-
po di scopo di assicurare che
i processi w3wp.exe e aspnet_
wp.exe siano già in esecuzio-
ne quando approderemo alla
WebForm1.aspx dell’applica-
zione WebGenerate.
Visto che ci siamo faremo in
Figura 3 Le 101 cartelle generate dal codice modo che questa ulteriore ap-
plicazione ASP.NET, che d’ora in
avanti chiameremo PreWebGe-
c:\times.txt
3324018372781,25;3324018383453,13;3324018383468,75
3324018575078,13;3324018575078,13;3324018575078,13
3324018661859,38;3324018677140,63;3324018677156,25
3324019487906,25;3324019488968,75;3324019489609,38
3324019663046,88;3324019663046,88;3324019663046,88
3324019748125,00;3324019748906,25;3324019749500,00
3324020183125,00;3324020184218,75;3324020185031,25
3324020275984,38;3324020275984,38;3324020275984,38
Scenario 2 - Prova 1
“First Execution, Gac, No
Native Images, No Tem-
porary ASP.NET Files (1
Class)”
Se utilizzate Visual Studio
.NET ricordatevi di registrare
in GAC gli assembly (nel codi-
ce allegato all’articolo c’è un
file batch GacAll.bat che lo fa
per voi) e quindi ricordatevi Figura 4 I risultati del test in forma grafica
di togliere e aggiungere nuo-
vamente il riferimento all’as-
sembly Class100.dll nell’ap-
plicazione ASP.NET WebGe- generando con ngen.exe le rispettive 100 im-
nerate. magini native.
Quindi ricompiliamo, facciamo ripartire IIS Questa scenario prende spunto dalle featu-
tramite iisreset.exe e svuotiamo l’intera di- res che il tool ngen.exe offre, ed ovvero, com-
rectory Temporary ASP.NET Files. pilare il codice nativo senza scomodare il JIT
Riapriamo il browser e puntiamo nuovamente a run-time.
all’indirizzo: http://localhost/PreWebGenerate/
WebForm1.aspx. Ora se andate a controllare Scenario 3 - Prova 1
la directory Temporary ASP.NET Files trovere- “First Execution, Gac, Native Images, No
te con grande stupore solo UNA (1) cartella, Temporary ASP.NET Files (1 Class)”
quella dell’assembly di code-behind. Se utilizzate Visual Studio.NET ricordatevi, la-
Quanto tempo avremo risparmiato? Le consi- sciando tutto in GAC, di generare le immagi-
derazioni sui tempi vediamole alla fine, intanto ni native dei 100 assembly e solo dopo di to-
terminiamo tutte le prove necessarie. gliere e re-inserire il riferimento all’assembly
Il file c:\times.txt viene scritto in append, Class100.dll nell’applicazione ASP.NET Web-
quindi prenderemo tutti i dati alla fine dei Generate.
test. In realtà questo passo è obsoleto in quanto,
per Visual Studio .NET è ininfluente l’esistenza
Scenario 2 - Prova 2 o meno di immagini native in fase di compila-
“Second Execution, Gac, No Native Ima- zione; se ne accorgerà solo il CLR - Common
ges, Temporary ASP.NET Files (1 Class)” Language Runtime - appunto a run-time.
Stesse modalità dello Scenario 1 – Prova 2. Nel codice allegato all’articolo c’è un file ba-
tch NativeAll.bat che lo fa per voi.
Scenario 2 - Prova 3 Quindi ricompiliamo, facciamo ripartire IIS
“First Execution, Gac, No Native Images, (iisreset.exe) e svuotiamo l’intera directory Tem-
Temporary ASP.NET Files (1 Class)” porary ASP.NET Files.
Stesse modalità dello Scenario 1 – Prova 3. Riapriamo il browser, puntiamo nuovamente
all’indirizzo: http://localhost/PreWebGenerate/
Scenario 3 - “Gac, Native Images” WebForm1.aspx e procediamo come già illu-
Analogamente allo Scenario 1 e 2 condurre- strato in precedenza. Ora se andate a control-
mo anche qui le stesse tre prove ma stavolta lare la directory Temporary ASP.NET Files trove-
non solo tenendo in GAC tutti e 100 gli assem- rete sempre e solo una (1) cartella, quella del-
bly (Class100.dll, Class99.dll, … Class1.dll) ma l’assembly di code-behind.
Questo dimostra come vere le perples- Ma perché vengono copiati nella directory
sità prima ipotizzate sull’utility ngen.exe. Temporary ASP.NET Files\WebGenerate\
Il JIT compila ed applica delle ottimizzazio- ...? Non potrebbero restare lì dove sono?
ni di compilazione a JIT-compile-time, che Questo comportamento è dovuto al fatto che
ngen.exe, a native-compile-time, non può l’assembly di code-behind della nostra appli-
nemmeno lontanamente immaginare di fare. cazione WebGenerate verrà preso in carico
Inoltre è noto che le immagini nati- dal processo aspnet_wp.exe nella directory
ve restano confinate nel loro Applica- Temporary ASP.NET Files\WebGenerate\...
tion Domain e quindi comunque non po- e non nella directory \bin, meccanismo ne-
trebbero essere utilizzate da ASP.NET cessario alla “fusione” tra codice di scrip-
che è invece Cross Application Domain. ting lato server e code-behind. Questa fu-
Notate che la differenza tra Scenario 3 e Sce- sione non può essere attuata nella cartel-
nario 2, in tutte e tre le prove è di circa 0,2 la \bin (non ci piace che la nostra cartel-
secondi quindi abbastanza trascurabile; ma la venga “sporcata”), occorre invece una
perché perderli? E soprattutto perché dover cartella temporanea: la directory Tempo-
rigenerare a manina le immagini native a fron- rary ASP.NET Files\WebGenerate appunto.
te di ricompilazione degli assembly? Questo è tra l’altro il meccanismo che ci
• Lo Scenario 1 segue in coda con le peggio- consente di ricompilare una applicazio-
ri performance di start-up in assoluto (ov- ne ASP.NET mentre essa è in esecuzio-
vero quello che tutti noi di solito usiamo). ne; l’assembly nella directory \bin è infatti
ASP.NET perde la maggior parte del tempo a sempre libero da ogni vincolo di ownership.
“copiare” i 100 assembly ed a creare tutta la Ora, visto che:
struttura su file system (vedi prova 3 dello sce-
nario 1), nella directory Temporary ASP.NET • quando un assembly a fa richiesta di un
Files\WebGenerate - 220 file in 207 cartelle. assembly b … b deve essere portato nel-
la stessa directory (o sotto directory) del- Tali conclusioni dovrebbero portarci anche a
l’assembly a (a meno di non usare un co- capire quale è stato il motivo per il quale, in
debase o la GAC). fase di installazione del .NET Framework, alcu-
• nel caso della nostra applicazione (Web- ni assembly siano stati registrati anche in for-
Generate), l’assembly è WebGenerate.dll mato nativo. La presenza di un assembly con
che ormai vive in Temporary ASP.NET immagine nativa interrompe il meccanismo di
Files\WebGenerate\.... JITting in cascata sugli assembly da questo re-
• L’assembly richiesto è, nel primo caso, ferenziati. Sarebbe infatti dispendioso per il JIT
Class100.dll, quindi questo viene copiato tutte le volte ricompilare a run-time ad esem-
anch’esso in una sotto directory dell’as- pio, l’assembly System.dll.
sembly richiedente (Temporary ASP.NET In conclusione non voglio impartire istruzio-
Files\WebGenerate\....). ni su cosa fare, ad esempio condividere tut-
• L’assembly Class100.dll fa poi richiesta to con codebase o pubblicare tutto in GAC o
a sua volta di Class99.dll … e in cascata non utilizzare mai ngen.exe. Spero soltanto di
vengono quindi copiati tutti in Temporary aver acceso una piccola luce sui meccanismi
ASP.NET Files\WebGenerate\.... che ASP.NET innesca dietro le quinte, quan-
do un’applicazione web parte la prima volta;
È proprio questa operazione di “copia” ed “in- lascio a voi ogni considerazione sul da farsi,
colla” che rende il nostro famigerato “primo caso per caso.
avvio” lento … lentissimo. Solo a partire dal .NET Framework 2.0, sarà
Successive richieste, fatte alla stessa appli- possibile finalmente e veramente pre-compila-
cazione, a patto di non aver alterato il conte- re le applicazioni ASP.NET e soprattutto creare
nuto della Temporary ASP.NET Files, saran- immagini native attraverso una nuova versione
no estremamente più performanti perché non del tool ngen.exe, che promette stavolta dav-
innescheranno più lo stesso meccanismo, in vero miracoli.
quanto tutto l’occorrente è già nelle directory Vi rimando, in bibliografia, ad un articolo mol-
in questione. to interessante di Reid Wilkes - MSDN Maga-
zine, aprile 2005 – che anticipa le caratteristi-
che salienti e più interessanti della nuova ver-
sione del tool ngen.exe presente nell’SDK del
L’obiettivo principe è .NET Framework 2.0.
Le novità VB
nel nuovo
Visual Studio
La nuova versione di Visual Studio porta con sé diverse interessanti novità relative al
linguaggio Visual Basic
di Lorenzo Vandoni
N
el momento in cui scrivo è stata resa dispo- Public Class Lista(Of T)
nibile la seconda beta della nuova versione di Private moItem() As T
Visual Studio 2005. Molte, come spesso ca-
pita, sono le novità. In questo articolo cercheremo di Public Sub Add(ByVal oItem As T)
concentrarci sugli aspetti sintattici e semantici relati- ...
vi al linguaggio Visual Basic. End Sub
End Class
L’avvento dei generics
La parola chiave Of serve ad in-
La novità principale è costituita dalla possibilità di uti- dicare un parametro di tipo gene-
lizzare la programmazione generica. In pratica, diventa rico, in questo caso rappresenta-
possibile creare delle classi del tipo “lista di X”, dove to dal marcatore T. Per usare que-
X è un tipo qualsiasi, oppure delle funzioni di ordina- sta classe si potrà scrivere:
mento in grado di ordinare oggetti di classi diverse.
La programmazione generica permette di creare fun- Dim oLista1 As New Lista(Of Integer)
zioni e classi in grado di utilizzare oggetti di un gene- Dim oLista2 As New Lista(Of String)
rico tipo T, offrendo la possibilità di validarne la cor-
rettezza durante la compilazione. I vantaggi principali La dichiarazione di questi due
di questo approccio, già discusso in questa rubrica, oggetti provocherà due diverse
sono quelli di consentire una maggiore efficienza, e di istanziazioni della classe gene-
permettere un maggiore controllo del codice. Non sarà rica, in cui il marcatore T verrà
possibile, infatti, introdurre delle stringhe all’interno di rispettivamente sostituito dai tipi
una classe definita come lista di numeri interi. La de- Integer e String. In questo modo,
finizione di una classe generica in Visual Basic.NET una chiamata del tipo
può essere scritta in questo modo:
oLista1.Add(“abc”)
• Un’altra interessante innovazione è costi- casi abbiano una loro utilità. Il fatto che siano
tuita dalla parola chiave My, che fornisce stati resi disponibili anche in Visual Basic può
un percorso di accesso alternativo a mol- essere comodo soprattutto nel caso in cui si
te tra le classi più utilizzate del framework. debbano richiamare funzioni C che usino uno di
Per esempio si può scrivere My.User.Identity questi tipi come parametro o valore di ritorno.
per accedere alle informazioni relative al- • Un’altra cosa che non mi è mai piaciuta mol-
l’utente dell’applicazione. In modo analo- to, è la possibilità di utilizzare, fino a Visual
go, My.Computer e My.Application permet- Basic 6, istanze “implicite” di form, scriven-
tono di accedere rapidamente alle informa- do ad esempio
zioni relative al sistema e all’applicazione.
• La parola My può essere anche utilizzata per MyForm.Show
accedere da programma agli elementi del pro-
getto. Per esempio, si può aggiungere un ele- invece di
mento all’insieme dei Settings del progetto,
e accedere a quell’elemento da programma Dim x as New MyForm
scrivendo My.Settings.<NomeElemento> x.Show
• A molti sarà capitato di utilizzare operazio-
ni di cast non sicure, cioè di dovere esegui- Con Visual Basic 2005, questa possibilità è
re alcune operazioni dipendenti dal tipo di stata reintrodotta.
una variabile, senza conoscere esattamente
il tipo di quest’ultima. Per potere verificare L’ambiente di sviluppo
la correttezza del cast era finora necessa-
rio gestire l’eventuale eccezione all’interno Al di là degli aspetti strettamente legati al lin-
di un blocco try, in questo modo: guaggio, la nuova versione di Visual Studio por-
terà con sé diverse nuove funzionalità. Tra queste,
Try vale sicuramente la pena di citare la possibilità,
Dim y as MyType = CType(x,MyType) cara ai programmatori Visual Basic, di modifica-
Catch re il codice durante il debug. Questa funzionali-
End Try tà, non disponibile in Visual Studio 2003, è sta-
ta nuovamente introdotta con la versione 2005.
Viene ora offerta la possibilità di utilizzare una Sono stati inoltre introdotti diversi miglioramenti
scorciatoia, costituita dall’istruzione TryCast, che nell’editor di codice, che ora è in grado, come nel
consente di verificare l’avvenuta conversione sem- caso degli strumenti Office, di suggerire possibili
plicemente controllando che il valore della variabile correzioni per diversi tipi di errore, e di mostrare
di destinazione non sia uguale a Nothing: tramite tooltip i valori di variabili anche complesse
durante le operazioni di debug. Anche la finestra
Dim y as MyType = TryCast(x,MyType) Immediata è stata potenziata, e ora può essere
If y IsNot Nothing Then utilizzata, come con Visual Basic 6, anche quan-
do il programma non è in esecuzione.
In questo frammento di codice si può vede-
re anche un’altra delle novità minori introdotte Conclusioni
con Visual Basic 2005, cioè la possibilità di uti-
lizzare il nuovo operatore IsNot invece di scri- Abbiamo visto una veloce carrellata, non esausti-
vere If Not y Is Nothing. va, delle principali novità introdotte da Visual Ba-
sic 2005. Alcune sono sicuramente interessanti,
• È ora possibile associare regole di visibilità altre sono solo delle curiosità. La maggior parte
diverse alle due parti Get e Set di una stes- di queste novità non sono particolarmente origi-
sa proprietà. Si può fare in modo, cioè, che nali, ma solo adattamenti di strumenti già presen-
la parte Get sia pubblica mentre la parte Set ti in altri linguaggi, o reintroduzioni di funzionalità
sia privata o protetta. già presenti in Visual Basic 6. Con queste nuove
• I tipi unsigned, in C, non mi sono mai piaciu- aggiunte, Visual Basic diventa un linguaggio piut-
ti molto, li ho sempre considerati soprattutto tosto completo, avendo eliminato molte limitazio-
come un modo per compiere errori più facil- ni senza per questo perdere quella semplicità di
mente. Non si può negare però che in alcuni utilizzo che lo ha reso popolare.
Un motore di scripting
per l’ambiente .NET
Realizziamo un programma in grado di compilare ed eseguire al volo file di testo
contenenti codice VB.NET
Scripting
di Filippo Bonanni
H
o sempre considerato le tecnologie di scripting estensione che saranno compila-
tra gli strumenti più utili messi a disposizione ti ed eseguiti sul classico doppio
di un programmatore; ormai non conto più le click del mouse.
volte che ho utilizzato un file VBScript o JScript per Il programma completo di esem-
risolvere piccole (ma non solo) esigenze: disporre di pi e file di setup, chiamato Net-
file di testo contenenti codice che viene elaborato a Script, è disponibile sul sito ftp di
run-time da un interprete, facilmente modificabili e Infomedia; i file di script sono ri-
distribuibili, ha sicuramente contribuito a migliorare conoscibili per l’estensione .vbns
la mia vita di sviluppatore. (Visual Basic Net Script).
Purtroppo queste tecnologie presentano anche dei
limiti, primo fra tutti l’utilizzo di un linguaggio non ti-
pizzato, pertanto con l’avvento di .NET confidavo di Struttura del Programma
trovare un epigono del Windows Scripting Host che
mi permettesse di abbinare l’immediatezza dello scrip- Come già discusso in un pre-
ting alla potenza del codice “managed”. cedente articolo (Computer Pro-
Invece, per rimpiazzare i vecchi VBScript mi sono gramming n. 146 “Un DTS con
ritrovato a scrivere, oltre al codice, file batch per la XML e la Reflection di .NET”), la
compilazione, lasciandomi una sensazione di mal- compilazione a run-time in .NET
contento ogni volta che editavo, ricompilavo ed ese- è ottenuta mediante l’ausilio del-
guivo. Il programma descritto in questo articolo è il le classi contenute nei namespa-
frutto di tale insoddisfazione: un motore di scripting ce System.CodeDom.Compiler e
per .NET in grado di compilare al volo ed eseguire System.Reflection (vedi [1]); ciò
file di testo contenenti codice VB.NET. su cui ci focalizzeremo maggior-
Per rendere l’utilizzo assolutamente trasparente, ol- mente è l’utilizzo della Reflection
tre alla realizzazione dell’applicazione vedremo anche per ispezionare l’assembly com-
come creare un semplice setup che ci permetta di pilato a run-time in cerca della
abbinare al programma, dei file con una particolare classe contenente il punto d’in-
gresso (la Sub Main) e la logica
per referenziare in fase di com-
pilazione assembly di terze parti
Filippo Bonanni Si occupa di informatica dal 1998 ed al non registrati nella GAC.
momento i suoi interessi sono rivolti principalmente all’am- Il programma quindi è strut-
biente .NET. Attualmente lavora nel team di sviluppo della
turato secondo questa sempli-
D&T Informatica di Sesto Fiorentino in progetti web-based di
interfacciamento a sistemi AS/400 e di archiviazione ottica ce logica:
in ASP.NET. Può essere contattato tramite e-mail all’indirizzo
fbonanni@infomedia.it. 1. Recupero e lettura del file;
‘///<references>
‘/// <prv>C:\NetAssembly\test.dll</prv> bly da referenziare. Per farlo utilizziamo la
‘///</references> classe CompilerParameters del namespace
System.CodeDom.Compiler (vedi [1])
Questa struttura sarà estrapolata dal codice,
memorizzata in un oggetto XmlDocument e uti- Dim CompParam as New CompilerParameters()
lizzata per recuperare il percorso completo de-
gli assembly da referenziare. CompParam.GenerateExecutable=true
CompParam.GenerateInMemory = true
Recupero e lettura del file CompParam.IncludeDebugInformation = Debug
‘Carico in un XmlDocument il codice xml delle referenze dell’assembly che dobbiamo importare è me-
Dim doc as XmlDocument glio specificare una directory alternativa nella
Dim nodeList as XmlNodeList quale copieremo il file specificato nell’elemen-
to <prv> ; per farlo ricorriamo al file .config e
doc=New XmlDocument() all’elemento <probing> (vedi [1]) che permette
doc.LoadXml(xml) di specificare ulteriori percorsi di ricerca
HKEY_CLASSES_ROOT
|
|_.vbns (Predefinito=”NetScriptFile”)
|
|_ShellNew (FileName=”C:\Programmi\D&T Informatica\NetScript\Modelli\model.vbns”)
HKEY_CLASSES_ROOT
|
|_NetScriptFile (Predefinito=”File NetScript”)
|
|_DefaultIcon (FileName=”C:\Programmi\D&T Informatica\NetScript\NetScript.exe, 0”)
|
|_Shell (Predefinito=”Open”)
|
|_Debug (Predefinito=”Esegui con NetScript (debug mode)”)
| |
| |_command (Predefinito=””C:\Programmi\D&T Informatica\NetScript\NetScript.exe” %1 /d”)
|
|_Open (Predefinito=”Esegui con NetScript”)
|
|_command (Predefinito=””C:\Programmi\D&T Informatica\NetScript\NetScript.exe” %1”)
Realizzazione del Setup vo” del menu contestuale proprio come per
i file di Testo, Word, Excel ecc.
Per rendere l’applicazione comoda da utiliz-
zare occorrono tre cose: Tutto questo lo si può realizzare intervenendo
sul Registro di Configurazione tramite un sem-
• L’abbinamento dei file .vbns al programma plice file di script che eseguiremo per effettuare
in modo che vengano eseguiti sul doppio l’installazione; senza dilungarsi sulla struttura del
click del mouse Registry, analizziamo le voci che dovranno esse-
• L’aggiunta delle voci di “esecuzione” e di re scritte nella chiave principale HKEY_CLAS-
“esecuzione in modalità debug” al menu SES_ROOT. Creiamo la chiave .vbns che conter-
contestuale che appare cliccando col pul- rà il riferimento ad un’altra chiave NetScriptFile e
sante destro sui file .vbns il percorso completo del file modello da utilizzare
• La creazione di un file .vbns vuoto come quando l’utente selezionerà “File NetScript” dalla
quello del Listato 1 tramite la voce “Nuo- voce “Nuovo” del menu contestuale.
If nodeList.Item(i).Name=”prv” Then
‘Cerco il file come specificato nell’elemento <prv> e se non lo trovo provo a cercarlo nella
cartella in cui risiede lo script
If File.Exists(nodeList.Item(i).InnerText) Then
File.Delete(reference)
File.Copy(nodeList.Item(i).InnerText, reference)
Else
File.Delete(reference)
File.Copy(filepath & nodeList.Item(i).InnerText, reference)
Else
Throw New XmlReferenceException(String.Format(“Impossibile trovare il percorso dell’assembly {0}”,
nodeList.Item(i).InnerText))
End If
End If
End If
If File.Exists(reference) Then
CompParam.ReferencedAssemblies.add(reference)
Else
Throw New XmlReferenceException(String.Format(“Impossibile trovare il percorso dell’assembly {0}”, reference))
End If
End If
Next
sr=New StreamReader(filename)
CompParam.GenerateExecutable=true
CompParam.GenerateInMemory = true
CompParam.IncludeDebugInformation = Debug
CompParam.ReferencedAssemblies.add(“System.dll”)
CompParam.ReferencedAssemblies.add(“System.Data.dll”)
CompParam.ReferencedAssemblies.add(“System.Xml.dll”)
CompParam.ReferencedAssemblies.add(“System.Drawing.dll”)
CompParam.ReferencedAssemblies.add(“System.Web.dll”)
CompParam.ReferencedAssemblies.add(“System.Windows.Forms.dll”)
CompParam.ReferencedAssemblies.add(“System.Management.dll”)
CompParam.ReferencedAssemblies.add(“Microsoft.VisualBasic.dll”)
CompRes=Comp.CompileAssemblyFromSource(CompParam, sr.ReadToEnd())
‘Nel caso di errori li mostro a video
If CompRes.Errors.Count > 0 Then
For i=1 to CompRes.Output.Count-1
Console.WriteLine(CompRes.Output.Item(i))
Next
Else
‘Recupero del punto di ingresso dell’assembly generato
EntryPoint=CompRes.CompiledAssembly.EntryPoint.Name
for i=0 to CompRes.CompiledAssembly.GetTypes.Length - 1
If CompRes.CompiledAssembly.GetTypes(i).GetMember(EntryPoint).Length > 0 Then
t = CompRes.CompiledAssembly.GetTypes(i)
Exit For
End If
Next
Nel Riquadro 1 è mostrata una rappresenta- RegistryKey con il quale creare i valori all’inter-
zione della chiave creata; tra parentesi indichia- no della chiave selezionata. Di seguito mostria-
mo, a sinistra dell’uguale i valori stringa e a de- mo la scrittura della chiave .vbns
stra i dati in esso contenuti. Il percorso del file
modello è contenuto all’interno del valore strin- Dim rk as RegistryKey
ga FileName della chiave ShellNew. La chiave rk=Registry.ClassesRoot.CreateSubKey(“.vbns”)
NetScriptFile a cui punta il valore predefinito di rk.SetValue(“”,”NetScriptFile”)
.vbns è quella che contiene tutti i riferimenti al rk.close()
programma e precisamente: rk=Registry.ClassesRoot.CreateSubKey(“.vbns\\ShellNew”)
rk.SetValue(“FileName”,ModelDir & FileModello)
• Il nome che appare nella voce “Nuovo” del rk.close()
menu contestuale (“File NetScript”);
• Il riferimento all’icona associata ai file .vbns; Conclusioni
• Le due voci per l’esecuzione in modalità
normale e debug (rispettivamente la chiave Forse qualcuno si sarà accorto che nella tratta-
Open e la chiave Debug). zione abbiamo volutamente evitato di affrontare
l’argomento della referenza di assembly di terze
Il dato del valore stringa Predefinito della chia- parti registrati nella GAC: in questo caso infatti è
ve Shell indica quale, tra le sottochiavi presen- impensabile ricorrere alla soluzione di specificare
ti, è quella che contiene il comando predefinito l’intero percorso data la complessità della struttu-
da eseguire sul doppio click, mentre i dati dei ra di directory e sottodirectory, con nomi tutt’al-
valore stringa delle chiavi Open e Debug mo- tro che facili da ricordare. In un prossimo articolo
strano il testo che appare quando si clicca col affronteremo questa lacuna, realizzando un pro-
pulsante destro su un file .vbns. Il marcatore gramma che ci permetterà di specificare solo il
%1 è utilizzato dal Sistema Operativo per so- nome dell’assembly e interrogare in modo rapido
stituire ad esso il percorso completo del file di la GAC per conoscerne il percorso completo.
script che stiamo eseguendo. La scrittura nel
Registro di Configurazione è effettuata tramite Riferimenti
le classi Registry e RegistryKey contenute nel
namespace Microsoft.Win32 (vedi [1]); la prima [1] .NET Framework SDK - http://msdn.micro-
è una classe statica che fornisce un rapido ac- soft.com/netframework/support/documentation
cesso in lettura/scrittura a ciascuna delle chiavi [2] XPath Tutorial - http://www.w3schools.com/
principali del Registry, restituendo un oggetto xpath
di Andrea Benedetti
T
ra le varie novità introdotte con la nuova ver- o dove devono essere fatti calcoli
sione di SQL Server, sicuramente l’integrazione ed aggregazioni complesse.
con il framework .NET è quella che agli occhi Tutte le procedure che conten-
dello sviluppatore risulta più intrigante. gono ed utilizzano cursori diven-
È necessario chiarire subito un punto: T-SQL, ov- tano quindi ottime candidate per
vero il dialetto proprietario di casa Microsoft, non una riscrittura in codice gestito.
è morto. Prima di questa versione l’unico
Anzi le nuove funzionalità ed i nuovi operatori sono modo per scrivere logica lato ser-
talmente tanti e tali che potrebbe essere necessa- ver era quella di costruire stored
rio rimettersi un po’ sui libri: large value data type, procedure estese che non pote-
event notifications, DDL triggers, pivot, row_num- vano fornire nessun controllo del-
ber, ecc… le risorse da esse utilizzate.
Il T-SQL, che si compone di linguaggio per le query SQL Server ci mette oggi a di-
e accesso ai dati e di linguaggio procedurale, re- sposizione un nuovo modello
sta, di fatto, l’unica scelta per recuperare e mani- di programmazione fornito dal-
polare dati (il CLR diventa un’alternativa alla scrit- la completa integrazione con il
tura di codice procedurale) e la scelta migliore con framework (versione 2.0), con il
comandi basati su set di dati. motore del CLR inserito diretta-
Conviene utilizzarlo sempre quando possibile ed mente nel motore di SQL Ser-
impiegare il CLR solo dopo aver verificato l’assen- ver (SQL Server fa da host al
za di istruzioni equivalenti o in presenza di logica CLR, quindi in un unico domi-
che non può essere espressa in maniera dichiarati- nio di applicazione); CLR che di-
va nel linguaggio di interrogazione. venta un’ottima e robusta alter-
Sicuramente possiamo trarne vantaggio, in termini nativa alla scrittura di procedu-
di performance, in tutti quei casi in cui, navigando re estese.
un set di record, dobbiamo “lavorare” ciascuna riga Infatti se un’applicazione client,
scritta in .NET, gira al di fuori di
un database ed accede ad esso
attraverso una connessione, con
Andrea Benedetti si occupa di disegno e manutenzione di
SQL Server 2005 siamo in grado,
basi di dati e di sviluppo di applicazioni web-based finalizzate
all’erogazione di servizi sanitari per conto di Studiofarma Srl invece, di scrivere codice gestito
di Brescia. Può essere contattato tramite e-mail all’indirizzo che verrà eseguito direttamente
abenedetti@infomedia.it. all’interno del database stesso.
Chiariamo che il runtime viene/verrà carica- Lo strumento di sviluppo utilizzato, Visual Stu-
to solo alla richiesta di esecuzione di codi- dio 2005, ci permette di utilizzare il medesimo
ce gestito. ambiente sia per scrivere ed effettuare debug
Se questa richiesta non verrà mai fatta, è evi- di applicazioni/oggetti database, sia per rea-
dente che il CLR non verrà mai caricato. lizzare applicazioni e componenti client.
Inoltre viene data la facoltà al DBA di disabi- Inoltre permette lo sviluppo di oggetti (fun-
litare completamente l’integrazione con il fra- zioni, procedure, trigger, tipi e aggregazioni),
mework (di default è già così, quindi per uti- operazioni di debug ed installazione automa-
lizzarlo dovremo abilitarlo configurando appo- tica sul server.
sitamente il server). Di default i database di esempio non vengo-
no installati.
L’integrazione ed i principali benefici È necessario quindi, durante l’installazione,
entrare nelle opzioni avanzate e selezionare i
Per iniziare a prendere dimestichezza con database interessati (database che, eventual-
questo matrimonio annunciato, abbiamo co- mente, possono anche essere installati in un
struito una macchina di test (una macchina vir- secondo momento).
tuale ospitata in Microsoft Virtual PC con si- Come abbiamo appena detto, di default, il
stema operativo Windows Server 2003 Stan- CLR viene disabilitato. Possiamo vedere la
dard Edition) in tre passi: installazione Visual configurazione estesa (Figura 1) del server
Studio 2005 (in beta 1), disinstallazione del con queste semplici istruzioni:
Framework 2.0 (non può essere soprascritto)
e, per finire, installazione di SQL Server 2005 USE master
(in beta 2). GO
eseguito direttamente all’interno del database Questa classe espone il metodo GetConnec-
sotto forma di stored procedure, user-defined tion() che ritorna un oggetto SqlConnection che
function, triggers, ecc... implementa l’interfaccia ISqlConnection.
Il codice scritto ed eseguito non dipenderà La SqlConnection ritornata ha alcune diver-
in alcun modo dalle connessioni al database. sità rispetto al medesimo oggetto esposto dal
Infatti nella scrittura di procedure e funzioni namespace SqlClient: non esiste un costrutto-
non sarà necessario creare connessioni (come re per la classe (si può solo utilizzare tramite il
era invece indispensabile nella scrittura di sto- metodo statico GetConnection()), esiste un nuo-
red procedure estese) grazie alla classe Sql- vo metodo CreateExecutionContext, non imple-
Context. menta l’interfaccia IDisposable (quindi non è
mand di cui abbiamo impostato il comando da collezione Assemblies sempre all’interno del-
eseguire ed il parametro necessario. la voce “Programmability”.
Scritto il codice non ci resta che effettuare Clicchiamo con il tasto destro sul nostro as-
l’installazione del nostro progetto: dal menu sembly per visualizzarne le proprietà ed ana-
“Build”, “Deploy Solution”. lizzare la voce “Permission set”.
Con questa operazione Visual Studio 2005 Per gli assembly caricati all’interno di SQL Ser-
genera ed esegue le necessarie istruzioni SQL ver, e quindi per il codice gestito, esistono tre
per installare l’assembly all’interno del databa- categorie di sicurezza (Code Access Security):
se e per creare la stored procedure costruita SAFE, EXTERNAL_ACCESS, UNSAFE.
nel codice (si può verificare facilmente apren-
do una traccia di SQL Profiler per visualizza- • SAFE è il set di permessi di default, permet-
re le istruzioni che vengono eseguite diretta- te di eseguire calcoli ed accesso ai dati uti-
mente sul server). lizzando il provider in-process, è l’equiva-
A questo punto non ci resta che aprire SQL lente di una procedura scritta in T-SQL.
Server Management Studio, espandere il nodo • EXTERNAL_ACCESS viene utilizzato in sce-
Databases del nostro server, espandere il db nari in cui si rende necessario accedere a ri-
AdventureWorks, “Programmability” e “Stored sorse esterne al server (ad esempio lettura/
Procedures”. scrittura file).
Possiamo notare che, oltre ad essere pre- • UNSAFE quando un assembly richiede ac-
sente la procedura up_SelectProductsTSQL, cesso a risorse particolari (ad esempio le
creata poco fa, esiste anche la procedura up_ API Win32).
SelectProducts installata direttamente dall’am-
biente di sviluppo insieme all’assembly Sql- Nelle prime due categorie il runtime si preoc-
ClrTest che possiamo trovare all’interno della cupa di verificare che il codice sia type-safe per
Image
Varchar
Char
Text
Ntext
Rowversion
SQL_variant Object
Table ISQLResultSet
Cursor
Timestamp
Xml SqlXml
lari o per accedere a risorse esterne (file, consumo e Write per abilitare il codice a leggere e scri-
di web service, ecc.) Proviamo a scrivere tre pic- vere lo stream di byte.
coli esempi che possano spiegare meglio l’utilizzo Impostiamo la proprietà MaxByteSize, uti-
di codice gestito con SQL Server 2005. lizzata solo con il tipo di formato che abbia-
mo impostato, così da indicare la dimensione
User Defined DataType massima dello stream, tenendo presente che
il valore non può superare gli 8.000 byte.
Vediamo come poter definire un UDT che Questa volta dopo aver scritto e compilato il
rappresenti il tipo “codice fiscale” (Listato 2). codice eseguiamo, a titolo di esempio, il cari-
Ancora una volta tasto destro sul nostro pro- camento dell’assembly e la creazione del tipo
getto, “Add”, “User-Defined Types” ed impostia- con istruzioni T-SQL, direttamente da una fi-
mo il nome come UDT_codiceFiscale.cs. nestra di query del Management Studio (Li-
La classe, decorata con l’attributo [Serializa- stato 3). Sicuramente non è opportuno co-
ble], prevede l’implementazione dell’interfaccia struire tipi personalizzati per entità comples-
INullable ed i metodi: ToString, Parse e Null. se (persona, impiegato).
Nell’esempio, banalmente, andremo ad in-
serire un membro privato di tipo stringa chia- User Defined Aggregate
mato “cf”.
Avendo una proprietà stringa, la classe non La scrittura di un UDA, ovvero una funzione
può avere un SqlUserDefinedTypeAttribute im- che lavora su di un set di righe e ritorna un
postato a Native in quanto soltanto i tipi che valore scalare (come le funzioni di aggrega-
hanno un’identica rappresentazione nel CLR zione sum, max, min, avg), può risultare molto
possono essere impostati come tali. più semplice ed il risultato molto più veloce e
Impostando tale attributo a Format.UserDefined meno pesante in termini di risorse.
è allora necessario implementare anche l’inter- Oggi, l’integrazione con il Framework ci forni-
faccia IBinarySerialize con i suoi membri Read sce questo nuovo modo per aggregare dati.
Riferimenti
Una volta eseguito il deploy del nostro pro-
getto possiamo eseguire, tramite una nuova [1] http://www.microsoft.com/sql/2005/
query nel SQL Server Management Studio (Fi- default.asp
gura 4), la nostra funzione: [2] newsgroup: microsoft.public.it.sql
I
n questa breve serie di articoli abbiamo finora esa- possibilità alle sottoclassi di A
minato i pattern Iterator e Observer, due tra i più di modificare il tipo dell’ogget-
famosi ed utilizzati tra quelli descritti nel libro “De- to creato. Alcuni esempi pos-
sign Pattern” di Gamma, Helm, Johnson e Vlissides. sono essere quello di una ge-
Questa puntata è dedicata ad un pattern meno noto, nerica collezione con un me-
chiamato Factory Method. todo che restituisca un itera-
tore, oppure quello di un og-
Il pattern Factory Method getto che rappresenti una con-
nessione a un database, con
Anche in questo caso la descrizione del pattern un metodo che restituisca un
verrà suddivisa in tre paragrafi, che evidenziano ri- oggetto command.
spettivamente lo scopo, le motivazioni e l’applicabi-
lità del pattern. • Applicabilità. Il pattern è appli-
cabile in tutti quei casi in cui il
• Intent. Lo scopo del pattern è quello di definire tipo dell’oggetto creato non è
una generica interfaccia che permetta la creazio- prevedibile a priori, oppure lo è
ne di un oggetto, delegando però alle sottoclassi ma si vuole offrire la possibilità
la scelta di quale tipo di oggetto istanziare. di crearne delle sottoclassi.
• Motivation. Questo pattern può essere utile so- Soluzione del problema
prattutto per chi si occupa della realizzazione di
framework o librerie di classi. In questi casi può La soluzione del problema è co-
capitare la necessità di definire, in una classe A, stituita dal diagramma di classi
dei metodi di creazione (metodi, cioè, che resti- mostrato in Figura 1. I paragrafi
tuiscano come risultato della loro esecuzione un seguenti ne forniscono una de-
riferimento ad un nuovo oggetto), offrendo però la scrizione più dettagliata.
co Product. Le sottoclassi di Creator hanno la di una classe più specifica, in questo caso
facoltà di fornire una versione specializzata di ConcreteProduct. Il FactoryMethod, ovvia-
FactoryMethod, che crea un oggetto più spe- mente, mantiene la stessa signature, e in
cifico, ConcreteProduct, derivato da Product. particolare continua a restituire un generi-
co riferimento ad un oggetto Product.
• Participants. Più in dettaglio, queste sono le re-
sponsabilità delle interfacce e classi coinvolte: • La classe ConcreteProduct deriva da
Product e rappresenta un caso concre-
• Creator è una classe base, che definisce to di oggetto creato dal FactoryMethod
il FactoryMethod. A seconda delle circo- (ad esempio, un iteratore forward only o
stanze, si potrà trattare di una vera clas- un comando per SQL Server).
se base, di una classe astratta o di una
semplice interfaccia. Questo dipende più
che altro dal fatto che la classe Product • Collaborations. La struttura dinamica del
abbia una semantica specifica, o possa pattern è molto semplice, e non vi sono par-
a sua volta essere considerata alla stre- ticolari collaborazioni da evidenziare tra gli
gua di semplice interfaccia. oggetti coinvolti. Semplicemente, un ogget-
to ConcreteCreator si preoccuperà di istan-
• La classe Product è una classe base che ziare un oggetto ConcreteProduct all’inter-
rappresenta un generico oggetto creato dal no della sua implementazione del metodo
FactoryMethod. Anche in questo caso si può FactoryMethod.
trattare di una vera classe, di una classe
astratta o di una interfaccia. Nel caso di col- Conseguenze e benefici
lezioni ed iteratori, ad esempio, può avere
senso creare un generico iteratore concre- Vediamo ora quali possono essere i punti di
to, con funzionalità di base applicabili a tut- forza della soluzione ed alcune sue possibili ap-
ti i tipi di collezioni. Nel caso di connessioni plicazioni pratiche:
e comandi, al contrario, non ha senso im-
plementare un generico comando. In ogni • Consequences. Il principale vantaggio è dato
caso, Product dovrà però definire i metodi dalla possibilità di aggiungere nuove classi
corrispondenti alla semantica dell’oggetto concrete come sottoclassi di Creator e Pro-
implementato (ad esempio, un iteratore o un duct, senza modificare la struttura del fra-
comando). Tali metodi verranno poi even- mework, e soprattutto senza dover modifi-
tualmente sovrascritti dalle classi derivate. care il codice delle applicazioni client.
Verificare
la disponibilità
di un control OCX
con VB6
A volte è necessario che un programma si comporti in modo diverso a seconda della
disponibilità di un determinato control OCX
di Lorenzo Vandoni
S
upponiamo di voler scrivere un programma Basterebbe infatti utilizzare la
che utilizzi un controllo OCX, senza sapere se seguente istruzione:
questo sarà effettivamente disponibile su tut-
te le macchine sulle quali il programma dovrà esse- CreateObject(“NomeDll.NomeClasse”)
re installato.
I motivi per cui una situazione del genere si può ve- Questa istruzione, nel caso in
rificare sono molti. cui l’oggetto in questione non
Il control in questione potrebbe costituire una fun- esista o non sia stato registra-
zionalità separata, disponibile a pagamento, oppure to, restituisce un errore del
potrebbe essere un control di terze parti, da acqui- tipo ActiveX component can’t
stare separatamente. create object. Sarà quindi suf-
Indipendentemente dal motivo per cui una situa- ficiente intercettare l’errore con
zione del genere si possa verificare, è interessante un’istruzione del tipo On Error
studiare una soluzione per questo problema perché, GoTo per poter prendere le con-
come vedremo, nonostante sia piuttosto semplice, tromisure desiderate.
non è del tutto ovvia. Con un control OCX que-
sta tecnica però non è appli-
La differenza tra OCX e DLL cabile.
Un control normalmente vie-
Se il componente non fosse implementato come ne aggiunto staticamente alla
controllo OCX, ma come ActiveX DLL, la soluzione form, in fase di design, e in ogni
al problema sarebbe molto semplice. caso non può essere creato con
un’istruzione CreateObject.
Nel caso il control sia aggiun-
Lorenzo Vandoni è laureato in Informatica, ed è uno spe- to staticamente alla form, però,
cialista di progettazione e sviluppo con tecniche e linguaggi
qualora l’applicazione venga in-
object-oriented. Ha collaborato alla realizzazione di framework,
strumenti di sviluppo e software commerciali in C++, Java e stallata su una macchina dove
Visual Basic. Può essere contattato tramite e-mail all’indirizzo quel control non sia disponibile,
vandoni@infomedia.it. si avrà un errore a runtime.
Controllo Remoto in
Visual Basic .NET
Prima puntata
Remote
di Stefano Corti
•
I
l linguaggio Visual Basic .NET può essere defini- Trasferire file dalla macchina
to a tutti gli effetti un moderno linguaggio di pro- locale alla macchina remota
grammazione orientato agli oggetti. Al pari di C# e e viceversa.
di Visual C++ .NET, costituisce parte integrante della • Ottenere le schermate video del
nuova piattaforma .NET di Microsoft che, insieme al- computer remoto.
l’ambiente di sviluppo Visual Studio, rappresenta un • Ottenere informazioni su alcuni
importante e raffinato riferimento per tutti i program- aspetti dell’hardware del com-
matori che desiderano sviluppare applicazioni per i puter remoto.
sistemi operativi Microsoft Windows. • Remotizzare in real-time la shell
Queste pagine costituiscono il primo di una serie di di DOS.
appuntamenti dedicati alla progettazione e allo svilup- • Operare sul registry del com-
po di un’applicazione completa in Visual Basic .NET. puter remoto.
Più precisamente spiegheremo in dettaglio i processi
per sviluppare un programma che consente di con- Analizzeremo in dettaglio alcu-
trollare, attraverso una rete basata su protocolli TCP/ ne importanti classi raggruppate
IP, una macchina remota. Realizzeremo quindi due di- in specifici namespace e ci de-
stinti applicativi; uno denominato “Controller” desti- dicheremo alla creazione di nuo-
nato a girare sul PC controllante ed un secondo ap- ve classi istanziabili per rendere
plicativo che chiameremo “Target” che dovrà essere operative le funzioni proposte. I
eseguito sulla macchina che ci prefiggiamo di con- programmi presentati non sono
trollare. Con l’applicazione che ci accingiamo ad illu- destinati ovviamente ad ambien-
strare potremo eseguire le seguenti operazioni: ti di produzione, ma ci offriranno
l’occasione di soffermarci attenta-
• Sessioni di chat-line tra Controller e Target in varie mente su alcuni importanti aspet-
modalità di dialogo. ti del linguaggio e della Class Li-
• Esplorare le unità logiche e le cartelle del compu- brary del .NET framework.
ter remoto.
• Creare nuove cartelle, rinominare e cancellare file Introduzione ai Socket TCP
sul computer remoto. e alle classi del namespace
System.Net.Sockets
Stefano Corti si occupa di programmazione PHP e JSP lato La nostra applicazione preve-
server, della piattaforma .NET e di integrazione di sistemi
de un modello progettuale di tipo
legacy con le nuove realtà del web, soprattutto in ambito ge-
stionale, bancario e finanziario. È attualmente alle dipendenze “Client/Server”.
di un primario gruppo bancario italiano. Può essere contattato Il programma Target in esecu-
tramite e-mail all’indirizzo scorti@infomedia.it. zione sulla macchina remota, è
a tutti gli effetti un server in ascolto su una dura Sub richiesta, che nel nostro caso risulta
determinata porta, pronto ad accettare le con- essere runServerTarget().
nessioni e le richieste di un client che, nel no-
stro caso, è costituito dal programma Controller. rThread = New Thread(AddressOf runServerTarget)
Utilizzeremo TCP come protocollo di traspor- rThread.Start()
to in quanto, a differenza dei socket di data-
gramma basati su UDP, è fortemente orienta- Si noti la presenza dell’operatore AddressOf
to alla connessione tra processi in esecuzione, che consente di creare un delegato di funzio-
laddove vi è un effettivo controllo della corretta ne che fa riferimento alla funzione specifica-
consegna dei pacchetti inoltrati. Dovremo suc- ta nell’argomento. Nel nostro caso si tratta di
cessivamente sviluppare un protocollo applica- una procedura Sub. Quindi invochiamo il me-
tivo basato su opportuni comandi a stringa li- todo Start() che innesca l’avvio del Thread. È
bera che verranno inviati dal Controller e che importante precisare che queste linee di codi-
dovranno essere comprensibili dal Target affin- ce devono essere collocate all’interno del co-
ché possa adeguatamente eseguire le opera- struttore della Form1 Sub New(), subito dopo
zioni richieste, al pari di quanto avviene con i la chiamata a InitializeComponent(), affinchè il
comandi di protocolli standard quali ad esem- Thread contenente la procedura runServerTar-
pio RETR, TOP, NOOP, DELE nel caso del pro- get() venga avviato nel momento in cui la Form
tocollo POP3 oppure GET e POST nel caso di viene caricata e inizializzata. In seguito tornere-
HTTP. Sceglieremo quindi uno o più numeri di mo maggiormente in dettaglio su questi aspetti
porta non assegnati da IANA (0 - 1023 well- delle procedure multi-threading. Ora focalizzia-
known port numbers) per mettere in ascolto i mo la nostra attenzione sulla progettazione det-
vari servizi esposti dall’applicativo Target. Os- tagliata del server di base, insieme al relativo
serviamo il Listato 1. client. Per prima cosa dobbiamo fare in modo
Per prima cosa dobbiamo importare nel pro- che l’indirizzo IP della macchina Target venga
getto alcuni namespace che contengono le clas- reso noto all’utente, affinchè possa essere co-
si richieste. Il namespace System.Net.Sockets municato al Controller, laddove il provider di
espone un certo numero di classi per la fun- connettività fornisca una soluzione basata sul-
zionalità di networking, mentre il namespace l’assegnazione di IP dinamici. Per ottenere l’in-
System.Threading contiene classi specifiche per dirizzo IP del computer Target, definiamo una
la definizione di procedure multi-thread. Abbia- particolare funzione che chiameremo getLoca-
mo scelto la porta TCP 13000 per porre in stato lIp() che riportiamo integralmente.
di ascolto il server di base, la cui procedura di
definizione è localizzata nella Sub runServerTar- Private Function getLocalIp() As Strin
get(). Il server di base ci consentirà di interpre- Dim HostName As String
tare ed eseguire la maggior parte dei comandi Dim indiIp As String
impartiti dal controller, per lasciare a procedure HostName = System.Net.Dns.GetHostName()
specifiche le funzionalità di trasferimento file e indiIp = System.Net.Dns.GetHostByName(HostName).
remotizzazione desktop Target. Per questi par- AddressList(0).ToString()
ticolari aspetti utilizzeremo altri numeri di porta. Return indiIp
Poiché è importante che i server in ascolto sul- End Function
le diverse porte siano in qualche modo sincro-
nizzati e contemporaneamente attivi, dovremo La funzione ritorna un valore stringa indiIp
inserire le relative procedure Sub in altrettanti contenente l’indirizzo IP della macchina sulla
Thread separati, il cui ciclo di vita deve essere quale è in esecuzione. La classe Dns, appar-
inizializzato nel momento opportuno. Per ora tenente al namespace System.Net, espone il
occupiamoci del Thread principale, al cui in- metodo GetHostName() che consente di otte-
terno è in funzione il server sulla porta 13000. nere il nome host del computer locale, passa-
Prima di tutto dobbiamo istanziare un nuovo to alla variabile stringa HostName. Tale stringa
oggetto Thread che chiameremo rThread. De- viene poi passata come parametro del meto-
finiamo rThread privato in quanto non vogliamo do GetHostByName(); tale metodo esegue una
che sia visibile all’esterno della classe Form1 e query nel server Dns per ottenere informazio-
poi creiamo un oggetto rThread passando come ni sull’Host specificato. Il valore ritornato è di
parametro del costruttore il nome della proce- tipo IPHostEntry ed è relativo all’omonima clas-
se; tale classe presenta il metodo AddressList() Premendo un apposito pulsante il nostro indiriz-
che recupera un array di tipo IPAddress con- zo IP verrà anche visualizzato in un TextBox.
tenente una lista di indirizzi IP risolti a partire
dal nome Host (nel nostro caso utilizziamo l’in- Private Sub showIpButton_Click(ByVal sender As
dice 0 dell’array in quanto dobbiamo ottenere System.Object, ByVal e As System.EventArgs)
un solo indirizzo di base). Il metodo ToString(), Handles showIpButton.Click
infine, converte il tipo ritornato in una stringa e ipText.Text = “Indirizzo IP da comunicare al
lo assegna alla variabile (string) indiIp. Ovvia- Controller: “ & getLocalIp()
mente l’intera funzione verrà dichiarata privata End Sub
in quanto non vi è ragione per renderla visibi-
le all’esterno della nostra classe base Form1. La funzione getLocalIP() ci servirà anche per
Provvediamo quindi a visualizzare l’informazio- passare il valore dell’indirizzo IP alle relative
ne ottenuta nella barra del titolo del nostro ap- linee di codice che implementano un sempli-
plicativo Target. ce sistema di autenticazione essenzialmente
basato su controlli di assegnazione di indiriz-
Me.Text = “Remote Administrator - Target - Indirizzo IP: zi IP, nome utente e relativa password. Questi
“ & getLocalIp() aspetti li vedremo dettagliatamente in seguito.
Imports System.IO
Imports System.Threading
Imports System.Net.Sockets
cicli While End While e Do Loop While nidifica- ta la connessione fra gli end-point. Il secondo
ti. Il ciclo while più esterno costituisce in realtà blocco invece si occupa di intercettare eccezio-
un loop senza fine (While True) che viene in- ni generate da errori durante la lettura dei dati.
terrotto nel caso in cui venga generata ed inter- In questo specifico caso, dal momento che la
cettata un’eccezione. Il ciclo Do Loop While più connessione è già stabilita, includiamo nel bloc-
interno invece consente di stabilizzare il server co Finally tutto il codice che ci serve per rila-
affinchè sia in grado di continuare a ricevere i sciare le risorse occupate, invocando il meto-
comandi dal Controller. do close() per gli oggetti writer, reader, socket-
Tale ciclo si ripete a meno che venga ricevu- Stream e connection (Listato 2).
to il comando TERMINATE e finchè la proprietà Un’analoga struttura di intercettazione di pos-
connected di connection (che abbiamo visto es- sibili eccezioni di tipo IOException dovrà esse-
sere un oggetto istanziato dalla classe Socket ) re implementata a livello client sull’applicativo
restituisce True. Notiamo che l’intera struttura Controller.
viene inserita in un blocco Try Catch End Try
all’interno del quale vi è un blocco Try Catch Realizzazione dell’architettura Client-Server
Finally EndTry. e implementazione del programma Controller
Abbiamo previsto il primo blocco per intercet-
tare possibili eccezioni sollevate nel caso si do- Vediamo ora come realizzare una vera e pro-
vesse verificare un errore mentre viene stabili- pria struttura di codice in grado di svolgere sem-
plici transazioni basa-
te sul modello Client-
Listato 3 Struttura del client
Server. Abbiamo vi-
sto, di massima, come
realizzare il program-
ma server. Ora ci con-
Private output As NetworkStream centreremo sulla pro-
Public Shared reader As BinaryReader
gettazione del client e
Public Shared writer As BinaryWriter
vedremo come i due
Public Sub runClientController() sistemi possono dia-
Dim client As TcpClient logare. È importan-
Try
Dim job As String() = Nothing
te capire che ciò che
Dim ip As String = inIP.Text dovremo essere in
Dim port As Int32 = CInt(inPort.Text) grado di estrarre dal-
client = New TcpClient() la sequenza binaria
client.Connect(ip, port)
output = client.GetStream()
in transito sul socket
writer = New BinaryWriter(output) aperto è sempre una
reader = New BinaryReader(output) sequenza di stringhe
inMessages.Text &= vbCrLf & “Ricevuto flusso I/O” & vbCrLf alfanumeriche, che
Try
Do contengono i coman-
messaggio = reader.ReadString() di del nostro protocol-
job = messaggio.Split(delimiter, 2) lo. Di fatto, per sem-
txtMessages.Clear() plificare, dovrà esse-
If (job(0) < > “REPLYDRIVESSEQUENCE” And _
job(0) < > “REPLYREMOTEFIL” And _ re possibile eseguire
job(0) < > “READYTORECEIVEFILE” And _ una sessione telnet
job(0) < > “REPLYREMOTEDIR” And _ sulla porta 13000 del
job(0) < > “REPLYBASESUBKEYS” And _
server in esecuzione
...
e quindi potere esse-
inMessages.Text &= vbCrLf & “Messaggio ricevuto da Macchina Target: “ & _ re in grado di esegui-
vbCrLf & messaggio re alcune transazioni
End If
semplicemente scri-
If job(0) = “ESTABILISHED” Then vendo i comandi di-
If job(1) = “AUTHREQUIRED” Then rettamente nel prompt
.... cmd.exe Osserviamo
il Listato 3.
Con questi valori specificati, il programma re residenti su due diverse macchine devono
Controller sarà in grado di connettersi al ser- scambiarsi per potere comunicare ed esegui-
ver che abbiamo precedentemente sviluppato. re le operazioni richieste. Come abbiamo visto,
Istanziamo quindi un oggetto di tipo Network- tali comandi testuali vengono iniettati sotto for-
Stream e due oggetti (writer e reader) di tipo ma di stream binari nei flussi socket Tcp aperti.
BinaryWriter e BinaryReader, analogamente a Adesso vediamo come ricostruire le sequenze
quanto abbiamo eseguito durante la progetta- e determinare i vari parametri passati come ar-
zione del server Target. gomento dei vari comandi.
In questo modo siamo in grado di estrarre dal- Ricordiamo che molti protocolli in uso sulle reti
lo stream binario i comandi stringa che ci ser- TCP/IP quali FTP, HTTP, POP3, SMTP, funzio-
vono. È bene notare che, in questo contesto, nano in questo modo. Di fatto, senza utilizzare
gli oggetti reader e writer sono dichiarati pub- alcun client basato su GUI, è possibile esegui-
blici e statici. re un Telnet sulla porta 110 del server remoto
Ciò significa che potranno essere direttamente ed eseguire una sessione di consultazione dei
invocati da altre classi, senza bisogno di crea- messaggi eventualmente presenti, utilizzando il
re nuove istanze. comando RETR oppure vedere solo il campo
Di fatto questi oggetti dovranno essere ac- header del messaggio seguito da un numero
cessibili ed utilizzabili da una seconda specifi- di linee specificate (comando TOP); potremo
ca classe che si occupa della remotizzazione infine cancellare determinati messaggi trami-
dell’editor del registro, di cui parleremo diffu- te il comando DELE.
samente in seguito. La stessa cosa può essere eseguita sulla
porta 21 dove si trova in ascolto il server FTP
Definizione del protocollo di comunica- (se previsto dall’amministratore del server re-
zione e dei comandi a stringa libera moto). Abbiamo chiarito questo concetto, dal
momento che il nostro server target si com-
Ora che abbiamo visto come stabilire una con- porta nel medesimo modo.
nettività di tipo client/server tra i due nostri ap- In pratica Controller e Target si scambiano
plicativi, vediamo subito come definire un sem- continuamente informazioni tramite determinati
plice protocollo applicativo basato su opportuni comandi che ora andremo a definire.
comandi a stringa libera che le due procedu- La nostra procedura è basata appunto su
questa tipologia di architettura, ad eccezione
delle routine di trasferimento file e remotizza-
Listato 4 Assegnamento alla variabile zione schermate desktop remoto, operanti su
oFileDirName differenti porte e con differenti modalità di tra-
sferimento dati.
L’estrazione dei comandi dallo stream bina-
Imports System
Imports System.IO rio è alquanto semplice utilizzando, come ab-
biamo detto, il metodo ReadString().
Public Class RemoteStructure Ogni comando è separato dal relativo para-
metro da uno o più caratteri speciali (abbiamo
Private oFileDirName As String
Private oInformation As String utilizzato il carattere > e il carattere | ). Vedia-
Private oReturned As String mo nella Tabella 1, a puro scopo esemplifica-
Private oDrive As String tivo, alcuni comandi implementati.
Private oSequenzaDrives As String
Private oSequenzaDirFil As String
Rammentiamo che è possibile visualizzare in
Private oUnits As String() uno specifico TextBox tutti i comandi che, a
Private oDirectoryList As String() basso livello, transitano tra le due procedu-
Private oDirectoryFileList As String() re, al fine di poter comprendere agevolmente
Private oStream As StreamReader
il meccanismo di comunicazione sottostante.
Sub New() Adesso ci dobbiamo occupare di scrivere il
Me.oFileDirName = “C:\” codice che svolge le funzioni di interpretazio-
End Sub ne di questi comandi.
Sub New(ByVal FileName As String)
Me.oFileDirName = FileName Abbiamo visto che nella stringa reply si trova
End Sub la sequenza estratta contenente il comando e
gli eventuali parametri operativi.
Generator
di Vito Vessia
L
a metafora dell’XML come linguaggio dei lin- zare un generatore automatico di
guaggi e come mezzo universale di interscambio classi VBScript che rimappino (e
delle informazioni è stata ironicamente descritta ne facciano da proxy) la struttu-
nella premessa di [1] come “XML has replaced Java, ra di un file XML qualunque, pur-
Design Patterns, and Object Technology as the sof- chè dotato di schema (interno o
tware’s industry solution to world hunger”… Al di là esterno). In realtà la struttura del
delle battute è indubbia l’importanza che ha assun- generatore di classi è semplice,
to ormai questo semplice e quasi banale formato di ma alquanto complessa da spie-
definizione dei dati nel mondo della comunicazione gare in modo astratto e sintetico
moderno. XML, nato come linguaggio di formattazio- in questa premessa.
ne dei contenuti, direttamente discendente da SGML, Quindi non vi resta che leggere
si è poi imposto come esperanto per qualsiasi infor- il seguito…
mazione si volesse produrre e distribuire.
Al punto che, da completo sistema di definizione dei Gli schemi XML
dati e quindi del contenuto, è diventato anche il lin-
guaggio di definizione dei contenitori dei dati e quindi Una interessante caratteristica
come vero e proprio protocollo applicativo. dell’XML è la possibilità di veri-
Un esempio per tutti è certamente SOAP, che usa ficare la correttezza sintattica di
proprio XML per definire un completo protocollo ap- un certo file rispetto ad un tem-
plicativo per realizzare un RPC (Remote Procedu- plate standard di riferimento det-
re Call). to schema.
Altrettanto straordinario è stato l’impatto che han- Infatti l’XML è di per sé un for-
no avuto i vari linguaggi di scripting nel mondo della mato piuttosto rigido, nel sen-
programmazione: hanno unito la potenza dei linguag- so che deve essere garantita la
gi di sviluppo tradizionali alla semplicità di scrittura correttezza sintattica, che preve-
e di deployment, in modo che qualsiasi ambito ap- de una lunga serie di regole da
plicativo potesse sfruttarne al massimo le peculiarità rispettare, perché il file XML si
senza che fosse dotato di una complessa infrastrut- possa definire well formed.
tura di compilazione e di runtime. Queste vanno dal chiudere ogni
Scopo di questo articolo sarà presentare uno stu- tag che viene aperto, all’uso de-
dio su un possibile utilizzo dello scripting per realiz- gli apici per i valori degli attribu-
ti, alla presenza di un solo nodo
padre per ciascun file e tanto al-
Vito Vessia È co-fondatore della codeBehind S.r.l. (http: tro ancora.
//www.codeBehind.it), una software factory di applicazioni Non sarà argomento di questo
enterprise, web e mobile, dove progetta e sviluppa applica-
articolo spiegare queste regole;
zioni e framework in .NET, COM(+) e Delphi di cui si occupa
degli aspetti architetturali. È autore del libro “Programmare la Rete e le librerie sono ormai
il cellulare”, Hoepli, 2002, sulla programmazione dei telefoni sature di materiale sull’XML. Un
cellulari connessi al PC con protocollo standard AT+.Può essere buon consiglio per la lettura è
contattato tramite e-mail all’indirizzo vvessia@infomedia.it. certamente [1].
La verifica sintattica però non è tutto, ma si ment), con la struttura di ogni attributo che
pone la necessità di definire un formato che contiene (xs:attribute) compresi i tipi e le even-
descrivesse le regole semantiche a cui il file tuali constraint (es. use=”required”).
deve adeguarsi perché possa essere compre- L’elenco dei nodi è flat, cioè non presenta
so anche da chi non ne è l’autore. la tipica struttura gerarchica dei file XML che
Proviamo ad immaginare di voler definire lega i nodi padre ai figli: questa gerarchia è
un formato standard di fatture da condivide- invece definita attraverso la presenza dei nodi
re con i nostri clienti e fornitori, e per far ciò xs:sequence definiti nei nodi xs:element.
vogliamo basarci su XML; dobbiamo altresì Il principio di funzionamento è molto sempli-
specificarne la logica (es. un nodo di testata ce: per verificare che il file XML sia semanti-
che si chiama HEADER, che contiene alcu- camente corretto rispetto allo schema di ri-
ni attributi come Number, Year e altri anco- ferimento deve soddisfare tutte le regole di
ra, poi devono esserci uno o più nodi di tipo quest’ultimo.
ROW e così via). Questa verifica di correttezza sarebbe un po’
troppo onerosa, anche se non impossibile, se
realizzata a mano affidandosi solo al nostro
colpo d’occhio, ma in realtà il compito è rea-
XML è di per sé lizzato egregiamente da un buon parser XML
di ultima generazione.
un formato Si intende cioè un parser in grado di ma-
piuttosto rigido nipolare e di comprendere gli schema XML
di ultima generazione definiti dal World Wide
Web Consortium [2].
Nel nostro esperimento utilizzeremo il nuo-
Lo schema XML serve proprio a questo. In vo e potente parser Microsoft XML Core Ser-
realtà gli schemi sono un’invenzione recen- vices (MSXML) 4.0.
te per l’XML: inizialmente il loro compito era Questo componente racchiude al suo interno
svolta dai DTD (Document Type Definition) un classico DOM (Document Object Model)
dalla logica molto simile. cioè un oggetto in grado di produrre un com-
Gli schemi hanno numerosi vantaggi: sono pleto object model a partire da un file XML,
XML essi stessi, supportano l’ereditarietà e un SAX (Simple API for XML) cioè un compo-
sono molto più potenti e completi. Osservia- nente che non conserva in memoria l’intera
mo ad esempio il Listato 1. struttura del file XML ma scatena degli eventi
Lo schema di riferimento del file XML ap- durante il parsing dello stesso.
pena mostrato è visibile nel
Listato 2.
In realtà l’esempio è stato
privato di numerosi attribu-
ti e di alcuni nodi per ridur-
ne l’occupazione tipografica,
ma rende l’idea.
Per consultare il codi-
ce Visual Basic si riman-
da al sorgente che accom-
pagna l’articolo, scaricabi-
le liberamente dal sito ftp:
//ftp.infomedia.it.
Possiamo notare come il file
XML presenti un riferimento
allo schema a cui soggiace
(Untitled2.xsd) e che lo sche-
ma non sia altro che un con- Figura 1 La gerarchia di oggetti dello Schema
tenitore di tutti i tipi di nodi Object Model
presenti nel file (nodi xs:ele-
<?xml version=”1.0”?>
<vCRM AUTHOR=”Vito Vessia” mlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”F:
\ScriptClasses\XMLClasses\disk\Untitled2.xsd”>
<ORDER DONE_NODE=”FALSE” CODE_SITE=”JRHOLD” CODE_CORRESPONDENT=”ARDILLO”
CODE_INVOICE_CUST=”029900” CODE_SHIP_CUST=”029900” CODE_ORDER_TYPE=”%” CODE_FAIR=”COD_FIERA”
CODE_PL_SOFA=”AJ” CODE_PL_ACCESS=”EF” CODE_CURRENCY=”ITL[~]” COD_CAUS_COMM=”G03”
COD_CAUS_PROD=”MAG” CODE_DOC_TYPE=”003”>
<HEADER_REMARK HRMRK_CODE_SITE=”JRHOLD” HRMRK_PROGRES=”1” HRMRK_CODE=”OCMC”
HRMRK_REMARK=”Maximum[~]Care” HRMRK_ON_CREDITS=”0” HRMRK_ON_DDT=”1” HRMRK_ON_LABEL=”0”
HRMRK_ON_INVOICE=”1” HRMRK_ON_OC=”1”/>
<ROW CODE_DBALT=”031615” CODE_PL=”AJ” ROW=”1” NUM_REVIS_ROW=”0” ORDER_SET=”2” PO=””
CODE_PART=”073504224”>
<ROW_REMARK RRMRK_CODE_SITE=”JRHOLD” RRMRK_PROGRES=”2” RRMRK_CODE=”OCMC”
RRMRK_REMARK=”Maximum[~]Care”/>
<COVER CODE_COVER=”15001011” CODE_QUEST=”Z0110001” FLG_ROW_MODIFIED=”” PROGR_RIV=”1”
NUM_REVIS_COVER=”0” CVR_CODE_SITE=”JRHOLD”/>
</ROW>
</ORDER>
</vCRM>
Public Property Let AUTHOR(valueField) oppure accedere in modo simbolico alla pro-
m_AUTHOR = valueField prietà:
End Property
End Class MsgBox oCRM.Attributes(“AUTHOR”)
dello ad oggetti. Nel caso specifico i nodi fi- IDispatch di COM come mostrato in [4]. Bre-
gli di Order sono HEADER_REMARK e ROW vemente vediamo come utilizzare direttamen-
e così via fino a completare la gerarchia (es. te da Visual Basic tali classi grazie al potente
vCRM.ORDER(2).ROW(3). COVER(1).CODE_ Microsoft Script Control [6] che è liberamente
QUEST). Si può vedere quindi come è possi- scaricabile dal sito di Microsoft e che sempli-
bile realizzare classi VBScript (o di scripting in fica drasticamente l’uso della tecnologia Acti-
generale in tecnologia Microsoft ActiveScrip- veScripting (il linguaggio usato sarà VBScript,
ting) che ripercorra, in forma più naturale ed alternativamente si sarebbe potuto usare qual-
immediata, la struttura di un file XML qualsiasi siasi altro linguaggio di scripting installato):
basandosi sullo schema a cui soggiace il file
stesso. Sarà così possibile istanziare queste ‘codice VBA
classi con i dati presenti nel file XML, infat- Dim oSC As Object ‘lo Script Control
ti ogni attributo del nodo XML è esposto nel- Set oSC = CreateObject(“MSScriptControl.ScriptControl”)
la classe in forma di property get/let che per- With oSC
metterà quindi anche di assegnare i valori di .AllowUI = True‘è permesso l’uso di interfaccia
queste proprietà: utente negli script
.Language = “VBScript”
vCRM.ORDER(2).TOT_SIT = 3 .UseSafeSubset = False ‘non impone nessuna
restrizione per la sicurezza
Realizzare un’intera applicazione in VBScript End With
è probabilmente poco pratico e ancor meno in- ‘a questo punto aggiungiamo il codice delle classi VBScript
teressante dal punto di vista dell’implementa- che effettuano il proxy dei nodi XML come visto in precedenza
zione in una situazione reale. oSC.AddCode “<codice della classe>”
Si da il caso però che sia possibile utilizzare
proficuamente tali classi in applicazioni Visual Fatto questo possiamo procedere all’istanzia-
Basic (VBA) o in generale in tutti quei linguag- zione di queste classi VBScript e al loro uso
gi ad alto livello capaci di gestire le interfacce all’interno di Visual Basic.
Infatti, trattandosi di normali istanze di inter- su nodi, sequence, ecc… Perché non affidar-
facce IDispatch per utilizzarle in Visual Basic è si quindi ad un generatore automatico di clas-
sufficiente ottenere il puntatore all’istanza del- si a partire da schema e di istanze delle classi
la classe stessa e assegnarlo ad un normale create in precedenza a partire da file XML che
Object o Variant. Questo è possibile sfruttan- soggiacciono allo stesso schema? Ebbene è
do il potente metodo Eval dello ScriptControl quello che andremo a realizzare, seppur in una
(e dello scripting più in generale) che permet- forma non esaustiva.
ta di valutare, facendosi ritornare il risultato in Il sorgente che accompagna l’articolo presenta
forma di variant, una qualsiasi espressione: il progetto Visual Basic di un ActiveX Dll (CPXML
Proxies.vbp) e di un progetto di esempio che
‘codice VBA utilizza tale engine (CPXMLProxyDemo.vbp)
Dim oCRM As Object sul file XML mostrato nell’articolo. Il motore
Set oCRM = oSC.Eval (“New vCRM”) è però generico e funziona su ogni XML con
schema standard [3] e utilizza il nuovo SOM di
A questo punto possiamo accedere a oMyOr- MSXML 4 per produrre le classi a partire dagli
der direttamente da codice Visual Basic esat- schema e il DOM per produrre le istanze delle
tamente come abbiamo fatto all’interno di VB- classi a partire dai nodi XML. Questo presen-
Script: ta solo due metodi pubblici. Il primo, Create-
ClassesFromXMLSchema, permette di produr-
‘codice VBA re una gerarchia di classi VBScript a partire da
oCRM.AUTHOR = “Vito Vessia” uno schema XML:
Msgbox oCRM.AUTHOR
‘codice VBA
Il Class Generator Public Function CreateClassesFromXMLSchema
(XMLSchemaObject As Variant, _
Il meccanismo appena mostrato è molto po- Optional XMLSchemaRef As Variant) As String
tente ma ha, nella forma in cui l’abbiamo mo-
strato, un’utilità quasi nulla perché ci permette Il primo parametro rappresenta proprio lo
sì di scrivere le nostre classi di proxy intorno ad schema da cui produrre le classi.
un qualsiasi XML con schema, ma ci costrin- È di tipo variant perché potrebbe essere sia il
ge comunque a scriverci manualmente, e per nome del file o la url dello schema e sia diret-
ogni differente schema, il codice di tali clas- tamente l’oggetto ISchema, ed infatti vengo-
si. Ci costringe inoltre, cosa ancora più inutile, no fatti i controlli del caso (una IsObject e una
a istanziare tali classi e a popolarle secondo i QueryInterface) per comprenderne la natura.
dati presenti nel file XML in questione. Il secondo parametro è passato invece per
referenza e viene usato come parametro di tipo
out, cioè viene valorizzato in uscita; in pratica
a questo viene assegnata l’istanza dello sche-
Le classi che andremo a pro- ma appena prodotto.
durre non perderanno nulla Il valore di ritorno della funzione è invece pro-
prio il codice sorgente delle classi.
delle caratteristiche dello A questo punto si procede scorrendosi la col-
lection elements dello ISchema, ciascun ele-
schema XML di cui vanno a mento rappresenta un diverso nodo dei file
realizzare il wrapper XML sottoposti allo schema dato.
Dopo più di due anni di esistenza la rubrica .NET Tools 2. Una volta giunto alla versione finale, il costo di ogni
si concede un “strappo” alla regola, ospitando in questo singolo prodotto sarà di ben (!) 49$!
numero una suite di prodotti che avrà un sicuro posto di
rilievo nel prossimo futuro, e che, a differenza dei software Da questo ovviamente va escluso Sql Server Express
recensiti normalmente, è a pagamento. che invece è – e rimarrà – completamente gratuito!
Ohibò! Perché questa decisione? Non c’è più software A questo punto nessuno ha più scuse; dal punto di
“free” disponibile? vista professionale, chi ancora non ha provato .NET lo
Assolutamente no, anzi…ma, come ormai saprete, i tempi potrà fare senza spendere nulla, mentre dal punto di
del rilascio del .NET Framework 2.0 e di Visual Studio vista didattico, chi vorrà, potrà essere sicuro di imparare
2005 (e di Sql Server 2005) sono sempre più vicini e, data (od insegnare) ad utilizzare un prodotto che è in tutto
l’importanza dell’evento, noi di VBJ non possiamo certo e per tutto simile a quello che, magari, un giorno, si
far finta di nulla! userà per lavorare.
È quindi importante farsi trovare pronti, magari andando Tenendo conto che nell’età scolastica (ed includo an-
a vedere cosa bolla in pentola sopratutto per quello che che il periodo universitario) chi sviluppa lo fa solamente
riguarda la programmazione free (o a bassissimo costo) per passione e per divertimento, cosa ci può essere di
di .NET 2.0. meglio che prepararsi al mondo professionale unendo
La suite di prodotti “Express” è stata pensata proprio l’utile al dilettevole?
con questo target in mente: far avvicinare tutti (ma pro-
prio tutti) gli sviluppatori a .NET, soprattutto quelli che Visual Studio Express Edition Products
non vogliono o non possono investire nell’intero Visual
Studio, ma che non vogliono comunque rinunciare a fare A differenza dei fratelli maggiori (da Visual Studio stan-
il salto di qualità verso la piattaforma .NET 2.0. dard in su) che permettono di scrivere codice indifferen-
Tralasciando però per un momento il discorso pura- temente in C#, VB.NET, J# e C++, e che permettono di
mente professionale, la possibilità di avere piattaforme sviluppare applicazioni Windows e Web, la suite Express
di sviluppo ottime ad un prezzo davvero basso, permette è strutturata in modo da diversificare gli ambienti di
di far iniziare la formazione informatica sin dalle scuole sviluppo a seconda del target e del linguaggio.
medie, dando la possibilità ai ragazzi interessati di potersi Per lo sviluppo di applicazioni Windows, a seconda
avvicinare subito ad uno strumento reale di sviluppo, del linguaggio che desideriamo utilizzare, possiamo
lasciando il buon GWBasic al suo posto, ovverosia… scegliere tra:
nell’armadio. A tal proposito ho recentemente avuto
un’ottima esperienza a Milano, dove, insieme ad un Visual Basic 2005 Express
collega ed a volenterosi professori e genitori abbiamo Visual C# 2005 Express
organizzato alcune giornate di formazione su Visual Visual J# 2005 Express
Basic 2005 per ragazzi delle scuole medie. Visual C++ 2005 Express
Il riscontro è stato molto positivo, soprattutto per i
genitori degli appassionati fanciulli che possono così Se invece vogliamo sviluppare siti web, è sufficiente
utilizzare Visual Studio senza doversi svenare. utilizzare un solo prodotto, che permette di scegliere se
Per due motivi: sviluppare in VB.NET, C# o J#:
1. Attualmente le versioni Express sono ancora in Beta Visual Web Developer Express
(benché piuttosto stabile) e l’utilizzo ed il download
sono completamente gratuiti. Tutti gli ambienti di sviluppo mettono a disposizione
praticamente lo stesso set di funzionalità; set davvero
molto ampio, tanto da farne prodotti quasi professionali.
Davide Mauri è un consulente freelance che si occupa di Per quanto riguarda la scrittura del codice troviamo le
SQL Server 2000 e di sviluppo di soluzioni Web basate sul ormai indispensabili funzionalità di syntax highlighting e
.NET Framework. All’attività di consulenza affianca una co- di Intellisense (anche conosciuto come auto-completion),
spicua attività di docenza e di formazione presso Mondadori che permettono di scrivere velocemente e possibilmente
Informatica. Il suo sito personale è www.davidemauri.it. senza errori il codice.
Tra le novità si trova l’implementazione del refactoring anche gli errori più semplici. Dall’ambiente di sviluppo
“Rename Method” (esteso di fatto ad ogni oggetto) che è possibile anche gestire database (non necessariamente
semplifica di molto la vita quando si vuole rinominare Sql Server) e nel caso della versione Web Developer
un oggetto. navigare nel sito che si sta sviluppando usufruendo del
Come si vede dalla Figura 1 (che mostra l’ambiente in web server integrato.
tutta la sua bellezza), quando si rinomina un elemento, A differenza infatti del predecessore Web Matrix, questo
Visual Studio Express se ne accorge e ci chiede se ambiente di sviluppo è completamente autosufficiente
vogliamo aggiornare tutti i riferimenti all’oggetto con il e non necessita dell’installazione di Internet Information
nuovo nome. Molto comodo! Server o di Cassini sul proprio computer.
Un altro nuovo strumento che aiuta a semplificare L’installazione del prodotto è molto semplice: una
ulteriormente la scrittura del codice è rappresentato volta scaricato l’eseguibile dal sito lo si lancia e lo si
dai Code Snippets. lascia lavorare. Penserà lui a scaricare tutto il necessario
Premendo la combinazione di tasti Ctrl+K e di seguito (.NET Framework 2.0 compreso) per far funzionare tutto
Ctrl+X appare un menù a tendina che ci chiede che correttamente.
cosa vogliamo fare. Prima di concludere, una nota riguardante la docu-
Dobbiamo aggiungere un proprietà alla nostra classe? mentazione e gli esempi forniti.
Nessun problema, scelta la voce adatta il codice verrà La documentazione è – come da standard Microsoft
generato in automatico e noi dovremo solo preoccuparci – piuttosto ricca; se questo però non bastasse le ricerche
di personalizzarlo! fatte all’interno della stessa possono essere automati-
Per quanto concerne l’esecuzione del codice, tutti gli camente estese al web, andando a cercare documenti
ambienti permettono di fare del debugging offrendo ed esempi di codice nelle community registrate su Co-
praticamente tutte le funzionalità delle versioni più co- deZone e su MSDN online, per essere sicuri di avere
stose, fondamentali per poter sviluppare un prodotto sempre informazioni recenti. Per quanto riguarda esem-
di buona qualità, senza dover impazzire nel cercare pi e tutorial, in ogni versione Express vengono forniti
SQL Server 2005 Express cui l’applicazione deve funzionare senza la presenza
di una connettività di rete, garantendo comunque
La versione Express di Sql 2005 prenderà il posto un’autonomia di funzionamento.
dell’attuale MSDN, senza però soffrire delle limitazioni Il tutto, come detto in precedenza, è supportato dalla
circa il numero di connessioni contemporanee suppor- presenza del Sql Server Express Manager, che mira
tate, dando quindi molto
più spazio ad un uso non
solamente personale ma
anche per piccole/medie
esigenze.
Oltre a questa grossa
ed attesa novità, un’al-
tra importante aggiunta
è quella – finalmente
– di uno strumento di
amministrazione e di
sviluppo, che prende
il nome di Sql Server
Express Manager.
La versione Express
supporta tutte le novità
introdotte da Sql Server
2005 senza escluderne
alcuna.
È pertanto possibile
sfruttare le potenzialità
fornite da XML, Web
Services, Service Broker,
.NET, le nuove estensio-
Figura 3 L’applicazione “videoteca” fornita come tutorial
ni al linguaggio T-SQL
e, interessantissimo, lo
sviluppo di report trami-
te i Reporting Services.
Tutto ciò “limitato” ad un
configurazione massima
che supporta:
1 Processore
1 GB di RAM
4 GB per Database