Concetti di base

Transcript

Concetti di base
Parte I
Concetti di base
In questa parte:
Capitolo 1: Introduzione al Microsoft .NET Framework............................................... 3
Capitolo 2: Concetti di base del linguaggio........................................................... 15
Capitolo 3: Flusso di controllo e gestione degli errori............................................... 85
Capitolo 4: Utilizzo di Visual Studio 2005............................................................ 125
Capitolo 5: Debugging di applicazioni Visual Basic................................................ 181
Capitolo 1
Introduzione al Microsoft
.NET Framework
In questo capitolo:
Un glossario .NET........................................................................................... 3
Nelle prime due edizioni di questo libro, che trattano le versioni 2002 e 2003 del
linguaggio Visual Basic .NET, ho utilizzato questo primo capitolo sul .NET Framework
per spiegare perché Microsoft ha deciso di investire così tante risorse ed energie
in questa nuova piattaforma di programmazione e perché dovrebbe causare una
rivoluzione silenziosa nel modo in cui si scrivono le applicazioni Windows e Web.
Tuttavia, sono passati tre anni e mezzo dal lancio del .NET Framework, e per questa
edizione del libro mi rendo conto che una tale introduzione sarebbe quasi superflua,
visto che molto è stato scritto sul .NET Framework nel frattempo. Dopo tutto, è
probabile che stiate leggendo questo libro perché avete già utilizzato Visual Basic .NET
in precedenza o che, come minimo, abbiate letto abbastanza sull’iniziativa .NET da non
aver più necessità di un ulteriore capitolo introduttivo.
D’altra parte, uno dei miei obiettivi è rendere questo libro il più consistente e
completo possibile, pertanto ho necessità di introdurre alcuni concetti che verranno
spiegati più in dettaglio in seguito nel libro. Alla fine, ho deciso di compilare una
sorta di glossario da poter leggere rapidamente per orientarvi nel labirinto .NET. Se
non si è nuovi al .NET Framework, si può certamente saltare questa parte o limitarsi
semplicemente a una rapida lettura.
A differenza di un glossario tradizionale, tuttavia, questi termini sono organizzati in
un ordine logico piuttosto che in ordine alfabetico. Ciascun termine rappresenta un
concetto importante che spesso si basa su termini già introdotti precedentemente.
Un glossario .NET
Assembly Una applicazione .NET può essere costituita da uno o più assembly.
Ciascun assembly è di solito un singolo file eseguibile EXE o DLL. Un assembly può
anche comprendere altri file, tra cui file .html, .gif o altri file non eseguibili. Gli
assembly rappresentano l’unità di versioning nel senso che tutti i file in un assembly
hanno lo stesso numero di versione. L’assembly è anche la più piccola unità logica di
deployment poiché non si distribuisce mai un sottoinsieme dei file che costituiscono
l’assembly. Tipicamente, una applicazione utilizza diversi assembly esterni, compreso
quelli che appartengono al .NET Framework stesso. Un assembly può comprendere
un file eseguibile o un file eseguibile più altri file di dati, ma gli assembly a file singolo
rappresentano di gran lunga il tipo più comune di assembly. Visual Studio 2005 può creare
3
4
Parte I Concetti di base
solo assembly a file singolo, pertanto per creare assembly multi-file è necessario eseguire a
mano il compilatore a riga di comando e il linker.
Common Language Runtime (CLR) Il .NET Framework utilizza una architettura stratificata,
alla base della quale risiede la API di Windows, come si vede in Figura 1-1. Il .NET Framework
offre una vista object-oriented delle funzioni del sistema operativo ma non le sostituisce,
pertanto gran parte delle invocazioni al .NET Framework vengono in definitiva risolte come
invocazioni a una delle DLL del kernel di Windows. Il CLR è il primo strato che appartiene al
.NET Framework. Questo strato è responsabile dei servizi di base .NET, tra cui la gestione della
memoria, la garbage collection, la gestione strutturata delle eccezioni, e il multithreading. Il
CLR si può considerare come il supervisore di tutte le applicazioni .NET: non si interagisce
mai direttamente con il CLR, ma tutte le proprie applicazioni vengono controllate da esso.
VB
C++
C#
JScript
...
Common Language Specification
ASP.NET
Windows Forms
Data and XML
Base Class Library
Common Language Runtime
Windows
COM+ Services
Figura 1-1 Gli strati del .NET Framework
Codice managed e unmanaged Si dice che le applicazioni .NET vengono eseguite come codice
managed poiché vengono eseguite sotto il controllo del CLR e ad essa è impedito eseguire
codice non sicuro che può mandare in crash la macchina o compromettere i propri dati. Ad
esempio, il CLR può impedire a una applicazione di accedere al filesystem o al registry di sistema
se l’applicazione è stata lanciata da una locazione su Internet che non è fully trusted (si veda
la definizione in seguito nel glossario). Per contro, si dice che le applicazioni non-.NET, come
le applicazioni Visual Basic 6, vengono eseguite come codice unmanaged, o codice nativo. Di
tutti i linguaggi prodotti da Microsoft, solo il C++ può produrre sia codice managed sia codice
unmanaged, ma anche gli sviluppatori C++ dovrebbero ricorrere al codice unmanaged solo
se strettamente necessario: ad esempio, per svolgere operazioni a basso livello o per motivi di
prestazioni, poiché solo il codice managed gode di tutti i vantaggi della piattaforma .NET.
Classi e tipi In gergo .NET, il concetto di tipo è più generico del concetto di classe. Più
precisamente, il .NET Framework definisce migliaia di tipi; i tipi .NET possono essere suddivisi
in due categorie generali: tipi reference (o classi) e tipi value. La gran parte dei tipi .NET sono
classi, pertanto il più delle volte si possono utilizzare indifferentemente i due termini. Si legga
il paragrafo “Tipi reference e tipi value” del Capitolo 2 per ulteriori dettagli.
Capitolo 1 Introduzione al Microsoft .NET Framework
Base Common Library (BCL) Il .NET Framework è costituito da diverse migliaia di tipi,
raggruppati in circa 30 assembly. Questi tipi permettono di eseguire pressoché ogni
compito immaginabile, compresa la visualizzazione di finestre, la lettura di file e l’invio di
testo HTML a un browser via Internet. La BCL è la parte del .NET Framework che definisce
tutti i tipi di dati di base, tra cui System.Object (la radice della gerarchia degli oggetti .NET),
tipi numerici e date, il tipo String, gli array e le collection. La BCL contiene anche i tipi
per la gestione delle caratteristiche principali di .NET, come l’I/O su file, il threading, la
serializzazione e la sicurezza. La maggior parte dei tipi appartenenti alla BCL sono compilati
negli assembly mscorlib.dll e System.dll.
Linguaggi .NET Gran parte delle funzionalità inglobate nei linguaggi tradizionali come
Visual Basic 6 ora fanno parte del .NET Framework e vengono esposte come tipi .NET.
Tutti i linguaggi .NET possono utilizzare questi tipi, e perciò tutti i linguaggi hanno le stesse
funzionalità. Ad esempio, anche se Visual Basic 2005 e Visual C# 2.0 hanno una sintassi
differente e keyword differenti, sono grosso modo equivalenti, ed entrambi permettono di
sfruttare la piena potenza del .NET Framework. Inoltre, tutti linguaggi disponibili per il .NET
Framework vengono compilati in codice IL (si veda la voce successiva del glossario), che a
sua volta viene infine compilato in codice nativo. Per questo motivo, non si noterà alcuna
differenza osservabile in termini di prestazioni tra linguaggi differenti. Un’eccezione a questa
regola pratica è che una applicazione C# che utilizza puntatori e codice unsafe può essere
eseguita in modo notevolmente più veloce rispetto all’equivalente applicazione Visual Basic.
D’altro canto, gli sviluppatori C# sono vivamente scoraggiati dall’utilizzare codice unsafe,
poiché l’assembly non è verificabile e potrebbe non essere eseguito a causa delle limitazioni
imposte dalla Code Access Security (si veda in seguito nel glossario).
Intermediate Language (IL) A differenza dei tradizionali linguaggi di programmazione, i
compilatori .NET non producono codice nativo che può essere dato in pasto direttamente,
ed essere eseguito, dalla CPU. Invece, producono il cosiddetto codice IL, che rappresenta una
sorta di linguaggio macchina per un processore virtuale che non corrisponde ad alcuna CPU
ad oggi disponibile. Mentre il codice IL è di livello più basso rispetto a gran parte dei moderni
linguaggi di programmazione, è di livello più alto rispetto al puro linguaggio assembly. IL è
un linguaggio stack-oriented che non indirizza direttamente i registri della CPU ed è dotato di
concetti di alto livello come le stringhe, le eccezioni e la creazione di oggetti.
ILDASM Visual Studio 2005 è dotato di un tool denominato ILDASM, o IL Disassembler. (In
una installazione di default di Visual Studio, si può trovarlo nella cartella C:\Program Files\
Microsoft Visual Studio 8\SDK\v2.0\Bin). Come fa intendere il nome, questa utility consente
di visualizzare il codice IL memorizzato all’interno di un assembly .NET permettendo di
trascinare semplicemente il file .exe o .dll da Windows Explorer nella finestra principale
di ILDASM. (Si veda la Figura 1-2). Per far sì che ILDASM visualizzi il codice sorgente
originale che ha prodotto l’assembly analizzato bisogna abilitare l’opzione Show Source
Lines dal menu View. (Il codice effettivo Visual Basic si vede solo se l’eseguibile ha un
file .pdb allegato che contiene informazioni simboliche). Utilizzerò spesso ILDASM in
questo libro per mostrare ciò che accade dietro le quinte e per commentare il codice
che il compilatore Visual Basic produce.
5
6
Parte I Concetti di base
Figura 1-2 Il tool ILDASM
Compilatore Just-in-Time (JIT)Poiché nessuna CPU può eseguire codice IL, il CLR deve convertire
questo codice in codice nativo mentre il programma è in esecuzione, lanciando il compilatore
JIT e passandogli l’indirizzo del metodo entry point (tipicamente, la procedura Sub Main in
una applicazione Visual Basic). Quando la procedura principale invoca altro metodi, il runtime
.NET utilizza il compilatore JIT per trasformare il codice IL all’interno di questi metodi in
codice nativo e poi esegue il codice nativo. Questa compilazione al volo viene svolta solo una
volta per metodo durante la durata dell’applicazione poiché il codice nativo viene mantenuto
in memoria e viene riutilizzato quando quel metodo specifico viene invocato nuovamente.
Metadati e Manifest Oltre al codice IL, un assembly comprende un insieme di tabelle che
contengono i cosiddetti metadati, ossia informazioni su quali tipi vengono compilati
nell’assembly, quali sono i relativi metodi, da quali assembly dipende questo assembly, e
via dicendo. Nel mondo del .NET Framework, i metadati sono importanti quanto l’effettivo
codice eseguibile poiché il CLR utilizza i metadati in molte occasioni. L’insieme più
importante di tabelle di metadati è noto come assembly manifest. L’aspetto notevole dei
metadati è che si possono estendere per mezzo di attributi custom, che offrono un modo
standard per includere ulteriori informazioni metadati in un assembly che non dipende da
uno specifico linguaggio di programmazione o da uno specifico compilatore.
Reflection La reflection è un insieme di tipi che consentono a una applicazione scritta per il
.NET Framework di leggere e utilizzare i metadati memorizzati in un assembly. Molte parti del
.NET Framework sono pesantemente basate sulla reflection, compresa la capacità di serializzare
il valore corrente di un oggetto su un file o di inviare oggetti a una applicazione in esecuzione
su un differente computer. La reflection verrà trattata in modo esaustivo nel Capitolo 18.
Native Image Generator (NGen) Il .NET Framework comprende l’utility NGen, che permette
di precompilare una applicazione .NET in codice nativo. Si noti che la precompilazione di
Capitolo 1 Introduzione al Microsoft .NET Framework
una applicazione non comporta necessariamente migliori prestazioni e, in alcuni casi, può
anche produrre codice più lento. L’utility NGen è più efficace con le applicazioni lato client
(ad esempio, le applicazioni Windows Forms), poiché riduce il tempo di avvio, ma è meno
utile con le applicazioni lato server, come i progetti Web Forms e Web Services, in cui il tempo
di avvio non è un fattore critico. Si noti che non si può utilizzare l’utility NGen per impedire
che un assembly venga decompilato (si veda il termine successivo), poiché un assembly
precompilato da NGen richiede comunque la presenza dell’assembly originale che contiene il
codice IL leggibile. Ulteriori informazioni sull’utility NGen sono disponibili nel Capitolo 17.
Decompilatori Alcune utility sul mercato permettono di analizzare un assembly .NET
compilato e di ricostruire il codice sorgente originale C# o Visual Basic. A mio avviso, il tool
migliore di questa categoria è Reflector (http://www.aisto.com/roeder/dotnet/), distribuito
come freeware e che offre l’opzione di decompilare il codice sia in Visual Basic sia in C#. Il
processo di decompilazione funziona così bene tanto da poter utilizzare questo tool come
tool di conversione inter-linguaggio: si compila un blocco di codice sorgente in Visual
Basic e poi lo si decompila in C#, o viceversa. Un ulteriore decompilatore molto diffuso è
Anakrino (http://www.saurik.com/net/exemplar/), anch’esso distribuito come freeware.
Obfuscator Poiché è così facile sbirciare in un assembly .NET, molte aziende sono molto
attente nel proteggere il proprio software da un decompilatore. Sfortunatamente, non si
può realmente proteggere un assembly dalla decompilazione. Tuttavia, si può “offuscare”
un assembly rinominando i nomi dei tipi e dei membri in stringhe prive di significato. Gli
utenti subdoli che decompilano il vostro assembly leggerebbero semplicemente un elenco
di sequenze di caratteri privi di senso. Inoltre, sarebbero ancora in grado di comprendere
cosa fa il vostro codice, ma questo compito richiederebbe molto più tempo e si può quindi
sperare che desistano. Visual Studio 2005 comprende il prodotto Dotfuscator Community
Edition della PreEmptive Solutions, che è più che adeguato per gran parte dei compiti
di “offuscamento”. (Si può eseguire questa utility dal menu Tools, si veda la Figura 13). Se si è alla ricerca di un prodotto più potente, andrebbe considerato l’acquisto della
Professional Edition di questo prodotto o di un ulteriore obfuscator in versione full come
Demeanor (www.wiseowl.com). Per ulteriori informazioni sugli obfuscator e sulle relative
caratteristiche (e anche di altri tool di programmazione freeware e commerciali) si visiti
la pagina http://www.howtoselectguides.com/dotnet/obfuscators/.
Figura 1-3 Il tool Dotfuscator Community Edition della PreEmptive Solutions
7
8
Parte I Concetti di base
Global Assembly Cache (GAC) Gli assembly del .NET Framework possono essere suddivisi
in due categorie: assembly privati e assembly pubblici. Gli assembly privati vengono
memorizzati nella cartella principale dell’applicazione e possono essere utilizzati solo da
questa applicazione (o da altri assembly della stessa cartella). Gli assembly condivisi di solito
vengono memorizzati nella Global Assembly Cache (GAC) e possono essere utilizzati da
tutte le applicazioni .NET in esecuzione sul computer locale.
La GAC è un’area dell’hard disk (posizionata nella directory C:\Windows\Assembly) in
cui il .NET Framework memorizza tutti gli assembly che possono essere condivisi tra tutte
le applicazioni .NET in esecuzione sul computer locale. Ad esempio, tutti gli assembly
che fanno parte del .NET Framework stesso vengono memorizzati nella GAC. Nella GAC
possono coesistere più versioni dello stesso assembly.
Versioning Il versioning rappresenta il problema di installare una nuova versione di
un componente su un computer senza influenzare il corretto funzionamento di altre
applicazioni che utilizzano una versione differente dello stesso componente. Il versioning
ha afflitto per anni gli sviluppatori Visual Basic 6 e COM, ma il .NET Framework lo ha risolto
in un modo molto raffinato. Per prima cosa, si possono evitare i problemi di versioning
utilizzando gli assembly privati: ciascuna applicazione può utilizzare una versione differente
di un assembly privato poiché gli assembly privati non vengono condivisi con altre
applicazioni .NET. In secondo luogo, si può installare un assembly condiviso nella GAC
poiché la GAC può sicuramente contenere più versioni dello stesso assembly. Ciascuna
applicazione compilata con la versione X.Y di un determinato componente continua a
funzionare correttamente anche se l’utente installa una versione più recente (o più vecchia)
dello stesso componente. Il versioning del .NET Framework è più flessibile del versioning
in COM. Infatti, uno sviluppatore o un amministratore di sistema può utilizzare un file di
configurazione per redirigere una richiesta per un determinato componente a una ulteriore
versione dello stesso componente. L’autore del componente può rilasciare una nuova
versione che corregge dei bug o che è più efficiente, e così facendo migliora indirettamente
la robustezza e la velocità di tutte le applicazioni che utilizzano quel componente senza
introdurre problemi di incompatibilità di versione.
Il versioning si estende anche al .NET Framework stesso. Quando diviene disponibile
una nuova versione del .NET Framework, si può installarla su un computer senza rimuovere
le versioni precedenti del framework, e le applicazioni che utilizzano le versioni precedenti
continueranno a funzionare. (Si veda la Figura 1-4.)
Deployment XCOPY
Se una applicazione .NET utilizza solo assembly privati, si può installarla semplicemente
copiando la cartella (compresa qualsiasi cartella figlia) dalla propria macchina di sviluppo alla
macchina del proprio cliente. Questo meccanismo è noto come deployment XCOPY. Questa
caratteristica non implica il dover utilizzare questo semplice metodo di installazione al posto
di una completa procedura di installazione. Tipicamente, è necessario creare dei collegamenti
nel menu Avvio e abilitare l’utente finale a selezionare quali parti delle applicazioni verranno
installate. Tuttavia, pur considerando questi compiti ausiliari, l’installazione di una
applicazione .NET è molto più semplice dell’installazione di una analoga applicazione COM a
causa del minor numero di cose che possono non andare a buon fine.
Capitolo 1 Introduzione al Microsoft .NET Framework
Figura 1-4
La directory Windows\Assembly di un computer su cui sono state installate
entrambe le versioni 1.1 e 2.0 del .NET Framework.
File di configurazione Le applicazioni .NET memorizzano le proprie impostazioni nei file
di configurazione, che vengono posizionati nella stessa directory dell’assembly principale
dell’applicazione. Il nome di un file di configurazione si forma accodando l’estensione .config
al nome dell’assembly. Ad esempio, l’applicazione myapp.exe utilizza il file di configurazione
myapp.exe.config. Essendo memorizzati nella cartella dell’applicazione, i file di configurazione
vengono installati correttamente quando si distribuisce l’applicazione utilizzando il
deployment XCOPY. Un file di configurazione utilizza la sintassi XML per memorizzare dati
gerarchici e perciò è più flessibile, ad esempio, dei file .ini. Le applicazioni ASP.NET possono
utilizzare ulteriori file di configurazione, uno per ciascuna sottodirectory che contiene una
parte dell’applicazione; ciascuno di questi file di configurazione secondari influenza le
impostazioni della parte corrispondente dell’applicazione. Uno speciale file machine.config
influenza tutte le applicazioni .NET in esecuzione su un determinato computer.
Ereditarietà La progettazione del .NET Framework è imperniata sul concetto di ereditarietà.
Tutti gli oggetti del .NET Framework formano una gerarchia con un’unica radice comune,
la classe System.Object, da cui derivano tutti gli altri tipi .NET. Questi tipi forniscono
funzionalità quasi in ogni area immaginabile, compresa l’interfaccia utente, l’accesso ai dati,
la programmazione Internet, l’elaborazione XML, la sicurezza, e la comunicazione intermacchina. Programmare in .NET spesso significa estendere uno di questi tipi. Ad esempio,
si può creare un controllo textbox che accetta solo numeri derivando una nuova classe dalla
classe System.Windows.Forms.TextBox e aggiungendo tutto il codice necessario che rigetta
gli inserimenti non validi. Le classi che non derivano da una specifica classe .NET ereditano
in modo implicito da System.Object e perciò traggono vantaggio in altri modi dal far parte
della gerarchia di oggetti .NET. Si noti che .NET supporta solo l’ereditarietà singola (il che
significa che una classe non può derivare da due o più classi).
Common Type Specifications (CTS) Questo set di specifiche stabilisce come un tipo espone
campi, proprietà, metodi e eventi; le CTS definiscono anche come un tipo può derivare da un
9
10
Parte I Concetti di base
ulteriore tipo e anche ridefinirne i membri. Poiché tutti i linguaggi .NET si attengono a queste
specifiche, possono scambiarsi dati, utilizzare tipi scritti in un linguaggio differente, e anche
ereditare da essi. Ad esempio, si può derivare una classe Visual Basic 2005 da una classe C#, e
si può scrivere una classe C# che implementa un’interfaccia definita in Visual Basic.
Common Language Specifications (CLS) Questo set di specifiche stabilisce le caratteristiche
minime che un linguaggio di programmazione deve avere per essere qualificato come
linguaggio .NET. Ad esempio, tutti i linguaggi .NET devono essere in grado di gestire tipi
primitivi, come le stringhe, gli interi, e gli array con base zero, e devono essere in grado di
processare una eccezione .NET lanciata quando si verifica un errore. Alcuni tipi del .NET
Framework non sono conformi alle specifiche CLS: ad esempio, gli array di array e gli array
con indice inferiore diverso da 0. Se la propria applicazione espone al mondo esterno degli
oggetti non CLS-compatibili, potrebbe essere inutilizzabile da altre applicazioni, in base al
linguaggio .NET utilizzato per svilupparle.
AppDomain Tradizionalmente, una applicazione Windows viene eseguita in un processo
Win32 distinto. Ciascun processo viene isolato da un altro processo per mezzo delle
caratteristiche hardware della CPU in modo che un processo non possa corrompere
accidentalmente la memoria e i dati che appartengono ad altri programmi. Nel mondo del
.NET Framework, tuttavia, le applicazioni vengono eseguite in un “dominio applicativo”, o
AppDomain. In uno stesso processo Win32 può essere in esecuzione uno o più AppDomain,
ma un assembly in un determinato AppDomain non può influenzare gli assembly in altri
AppDomain, anche se tutti gli AppDomain si trovano nello stesso processo Win32. (Si veda
la Figura 1-5). L’isolamento dell’AppDomain è ottenuto a livello software poiché tutti i
compilatori .NET producono codice “safe” che non può accedere a locazioni arbitrarie di
memoria. L’utilizzo di un unico processo che contiene più AppDomain consuma meno
risorse rispetto al suddividere l’applicazione in più processi e rende più agevole e più
efficiente la comunicazione tra assembly in AppDomain distinti.
Process 1
Process 2
AppDomain A
AppDomain D
AppDomain B
AppDomain E
AppDomain C
Figura 1-5 Un processo Win32 può ospitare più AppDomain. Gli AppDomain in esecuzione nello stesso
processo possono comunicare in modo più efficiente rispetto a degli AppDomain in processi differenti.
Applicazioni Console Le applicazioni Console sono programmi .NET che leggono i dati di
input e visualizzano l’output nella finestra console. Sono utili per la creazione di semplici
utility che si possono invocare da file batch ma rappresentano raramente una scelta
Capitolo 1 Introduzione al Microsoft .NET Framework
idonea per scrivere applicazioni commerciali. D’altro canto, le applicazioni Console sono
molto concise e per questo motivo gran parte degli esempi di codice di questo libro sono
progettati per essere eseguiti come applicazioni Console.
Windows Forms Windows Forms è la parte del .NET Framework che permette di creare le
tradizionali applicazioni Win32 in esecuzione su computer stand-alone o su computer che
fungono da client in una grossa applicazione client-server. Al contrario delle applicazioni
Web Forms, che sono programmi .NET che vengono eseguiti su un server e che inviano
l’output come testo HTML ai browser in esecuzione sui computer client (si veda in seguito
in questo glossario). La creazione di un progetto Windows Forms è simile alla creazione
di un progetto Visual Basic 6: si rilascia uno o più controlli sulla superficie del form, si
assegnano le proprietà nella finestra Properties, e si scrive il codice che deve essere eseguito
quando il controllo scatena un evento. In questo libro, mostro occasionalmente esempi
di applicazioni Windows Forms per illustrare le tecniche di programmazione che non
possono essere dimostrate per mezzo di progetti console.
Applicazioni ClickOnce ClickOnce è una nuova caratteristica della versione 2.0 .NET
Framework. In sintesi, un progetto ClickOnce genera una applicazione Windows Forms
che può essere lanciata da un computer remoto, o dalla intranet locale o da Internet. Le
applicazioni ClickOnce hanno un grande vantaggio rispetto a una ordinaria applicazione
Windows Forms: la facilità del deployment. L’utente finale deve solo cliccare su un
hyperlink nel browser per lanciare l’applicazione remota o per installarla sulla macchina
locale, in base a come il progetto ClickOnce è stato compilato. I programmi ClickOnce
possono essere eseguiti come applicazioni parzialmente trusted soggette alle restrizioni
della Code Access Security (si veda in seguito in questo glossario).
GDI+ Tutti i tipi del .NET Framework inerenti alla creazione di immagini e alla grafica sono
raccolti in GDI+. Si possono utilizzare le funzionalità GDI+ sia nelle applicazioni Windows
Forms sia nelle applicazioni ASP.NET. Ad esempio, si può creare un grafico a istogramma
sul server e inviarlo al client in una pagina HTML con una applicazione Web Forms, o
inviarlo a un client remoto attraverso un Web service.
ADO.NET ADO.NET è la parte del .NET Framework che consente di lavorare con i database
ed è perciò l’equivalente .NET della tecnologia ActiveX Data Objects (ADO). Nonostante
i nomi simili, ADO e ADO.NET sono molto differenti. Mentre ADO “classico” gestisce
virtualmente tutte le tecniche di database disponibili (compresi i cursori lato server e lato
client, i resultset disconnessi, e i batch update), ADO.NET si concentra principalmente
sui resultset disconnessi (detti DataSet nella terminologia ADO.NET) e non offre alcun
supporto per i cursori lato server. L’oggetto DataSet è molto più potente dell’oggetto
Recordset di ADO e può memorizzare dati provenienti da più tabelle dello stesso database o
da database differenti. Si possono creare relazioni tra differenti tabelle di dati, e si possono
importare o esportare sia i dati sia i metadati come XML.
ASP.NET ASP.NET è la parte del .NET Framework che permette di creare applicazioni
Internet e intranet. Le applicazioni ASP.NET possono essere suddivise in due categorie:
11
12
Parte I Concetti di base
applicazioni Web Forms e applicazioni Web Services (si vedano i due termini successivi).
Entrambi i tipi di applicazione condividono l’infrastruttura ASP.NET e utilizzano gli stessi
servizi: ad esempio, i servizi di caching e di sicurezza.
ASP.NET permette di creare applicazioni potenti e flessibili in una frazione del tempo
necessario con le tecnologie pre-.NET, come Active Server Pages (ASP). Questo parte del
.NET Framework è stata estesa e migliorata considerevolmente nella versione 2.0. Non
tratterò le applicazioni ASP.NET in questo libro.
Web Forms I progetti ASP.NET Web Forms creano applicazioni Internet e intranet che
producono una interfaccia utente e che “sembrano” venir eseguite all’interno di un
browser. Più precisamente, le applicazioni Web Forms vengono eseguite all’interno di
Microsoft Internet Information Services (IIS) e producono testo HTML che viene inviato
al browser del client. Grazie alla presenza di molti controlli utente (compresi controlli
complessi come griglie, calendari e treeview) si può scrivere una applicazione Web Forms
utilizzando lo stesso approccio a eventi che si utilizza per le applicazioni Windows Forms.
Web Service I progetti Web Service permettono di creare componenti che vengono eseguiti
su un computer remoto accessibile attraverso Internet. A differenza delle applicazioni Web
Forms, una applicazione Web Service non produce testo HTML: invece, le applicazioni
client comunicano con un servizio Web inviando una richiesta codificata in una grammatica
XML nota come Simple Object Access Protocol (SOAP). L’infrastruttura ASP.NET cattura
la richiesta, invoca l’oggetto in esecuzione all’interno di IIS, codifica il valore di ritorno
nuovamente in SOAP, e la restituisce al client.
L’aspetto notevole dei progetti Web Service è che Visual Studio genera automaticamente
una classe proxy per il client. Il codice dell’applicazione client utilizza questa classe proxy
e ne invoca i metodi come farebbe con un oggetto standard, ma la classe proxy converte
in modo trasparente queste invocazioni in invocazioni SOAP attraverso la rete. Il risultato
finale è che si può lavorare con un componente remoto come se fosse un oggetto locale.
Per ulteriori informazioni sulla libreria Web Services Enhancements (WSE), che estende
la tecnologia standard Web Services con caratteristiche come la sicurezza e le transazioni
si visiti l’indirizzo http://msdn.microsoft.com/webservices/webservices/building/wse/
default.aspx.
Remoting Il remoting è una tecnologia che abilita una applicazione .NET Framework a
invocare un metodo di un oggetto definito in un’altra applicazione in esecuzione in un
differente AppDomain, in un differente processo sullo stesso computer, o in un computer
differente della LAN o su Internet, utilizzando un canale di trasporto come TCP o HTTP. Il
remoting è estremamente efficiente poiché i dati vengono scambiati in formato binario (al
contrario dei Web Service, che scambiano dati sotto forma di testo XML).
Componenti Serviced I componenti serviced sono oggetti del .NET Framework che
possono interoperare con le applicazioni Component Services (COM+). I Web
service, il remoting, e i componenti serviced rappresentano le tre tecnologie del .NET
Framework che permettono di eseguire codice su un computer remoto, ma ciascuna
di esse espone vantaggi e difetti. I Web service consentono di comunicare anche con
Capitolo 1 Introduzione al Microsoft .NET Framework
piattaforme diverse da Windows ma sono relativamente inefficienti. Il remoting è la
tecnologia più efficiente del gruppo, ma può funzionare solo con altre applicazioni
.NET Framework. I componenti serviced sono a metà strada tra questi estremi poiché
possono interagire con altre applicazioni Windows (non necessariamente applicazioni
.NET Framework) e supportano appieno le transazioni e la sicurezza COM+.
Platform Invoke e COM Interop Il CLR consente a una applicazione .NET Framework
di interagire con applicazioni legacy, non .NET. Sono supportati due tipi principali
di interazioni: Platform Invoke (nota anche come PInvoke) e COM Interop. La prima
permette di invocare una funzione compilata in una DLL “classica”, scritta tipicamente
in C, C++ o in Borland Delphi. Ad esempio, grazie a Platform Invoke si possono
invocare i metodi dell’API di Windows.
COM Interop consente sia di invocare sia di essere invocata da un componente
COM, compresi i componenti scritti in Visual Basic 6. COM Interop è una funzionalità
critica nella migrazione di una applicazione legacy ad un linguaggio supportato dal
.NET Framework poiché permette di migrare un blocco di applicazione per volta pur
essendo ancora in grado di poter interagire con i blocchi dell’applicazione implementati
con la tecnologia più vecchia.
Code Access Security (CAS) Il codice managed viene sempre eseguito sotto la supervisione
del CLR. Ad ogni invocazione al .NET Framework, il CLR verifica che il codice chiamante
soddisfi le regole della Code Access Security e se ha il diritto di eseguire l’operazione
richiesta. Questi diritti dipendono dalla identità dell’assembly e dalla locazione da cui
viene eseguito. Più specificamente, solo agli assembly caricati dal disco rigido locale
vengono concessi tutti i permessi. (Questi assembly sono detti essere totalmente
trusted). Alle applicazioni lanciate da una condivisione di rete o da una locazione
intranet viene impedita l’esecuzione di operazioni potenzialmente pericolose, come la
lettura e la scrittura di file. Alle applicazioni che vengono eseguite da Internet vengono
concessi pochi o nessun permesso, in base a se l’URL di origine viene considerato un
sito trusted o meno. (Per definizione, si dice che gli assembly con permessi limitati
vengono eseguiti in un contesto di sicurezza parzialmente trusted.)
Il codice in esecuzione in un contesto parzialmente trusted non ha accesso al
filesystem locale, il che può rappresentare un serio problema se l’applicazione deve
salvare i dati tra le sessioni (ad esempio, le preferenze dell’utente). Per questo motivo,
il .NET Framework può gestire una piccola parte dell’hard disk locale come se fosse del
tutto isolata dalle altre cartelle. Questo parte è nota come isolated storage e ad essa
si può accedere anche da applicazioni che vengono eseguite da una locazione della
intranet o da un sito Internet.
13