Ciao a tutti,
a meta’ Ottobre 2009 mi sono laureato con il massimo dei voti all’Universita’ di Pisa e a meta’ Febbraio, dopo 4 mesi, ho iniziato una nuova vita e il mio primo lavoro a Cambridge. Ma andiamo con ordine…con questo post vorrei condividere con voi tutte le cose che sono avvenute in questo periodo e che mi hanno permesso di crescere tantissimo sotto ogni punto di vista.

Nel mese di Novembre e Dicembre per 6 Settimane ho frequentato un corso di inglese intensivo presso Regent School a Londra. E’ stata una esperienza bellissima che mi ha permesso di conoscere persone da ogni parte del mondo oltre a migliorare abbastanza il mio inglese e a portarlo ad un livello sufficiente per iniziare una vita all’estero. Ho provato a fare l’esame di Cambridge FCE ma purtroppo non sono riuscito a passarlo, lo riprovero’ in futuro. Per chi non lo sapesse a scuola sono sempre stato il primo della classe, ma l’inglese e’ sempre stato un grosso problema per me. Un motivo in piu’ per cui volevo assolutamente riuscire a vincere questa sfida con me stesso. Anche vivere in famiglia e’ stata una esperienza senz’altro positiva grazie alle belle chiaccherate, durante la cena, dopo pesanti giornate di 6/7 ore di studio dell’inglese.

Quando si raccontano le cose, dopo averle vissute, purtroppo si trascurano i dettagli, quelle piccole prime volte che pero’ fanno provare intense emozioni… come ad esempio arrivare in aereoporto la prima volta, parlare con la taxista durante il viaggio e gasarsi perche’ si riesce a conversare, fare il biglietto della metropolitana, parlare con uno sconosciuto alla fermata dell’autobus, gestire le faccende burocratiche per la scuola e l’alloggio in famiglia, acquistare la SIM inglese, fare il 999 e parlare al telefono con la polizia (si ho fatto anche questo), bersi un double beilis con il professore di inglese che e’ diventato un amico con cui chiaccherare, mangiare al ristorante e uscire con gli amici studenti, semplicemente girare per Londra e ammirare il tamigi la sera, andare al cinema,… in un paese straniero e’ come se dovessi rivivere da zero, e’ come rinascere… ogni cosa che fai e’ la prima volta e ho provato spesso la sensazione del bambino spaesato che cresce :) in effetti devo molto ai miei genitori che mi hanno sostenuto (soprattutto economicamente) nella mia avventura, da tanto desideravo diventare indipendente ed essere in grado di gestire autonomamente la mia vita… ora finalmente posso dire di esserlo (anche se devo ancora ricevere il mio primo stipendio, ma questo e’ un dettaglio). Debbo dire che provo una piacevole sensazione di liberta’ e di soddisfazione che in questo momento mi rende davvero felice.

Dopo il corso di inglese, ho passato delle piacevolissime vacanze natalizie in Italia con i miei genitori, la mia ragazza Michela (italiana) e i miei amici. Prima di rientrare in Italia pero’ mi sono dovuto mettere alla ricerca di un appartamento temporaneo dove vivere durante la ricerca del lavoro. Dopo qualche giro a Londra a visitare qualche appartamento alla fine l’ho trovato in Leytonstone e ho iniziato a vivere li a partire dall’8 Gennaio 2010. Un appartamento in condivisione con 5 persone. Sono sempre stato un bamboccione (coccolato e servito da mamma) quindi devo rimboccarmi le maniche anche con le faccende domestiche: cucinare, lavare, stirare (odio profondamente farlo), pulire ecc ecc.

Una volta che mi sono sistemato nel nuovo appartamento, a parte qualche altra lezioncina di inglese, ho iniziato a cercare attivamente lavoro. Ho fatto una ricerca molto attenta, ho letto libri su come scrivere il CV, prepararsi ai colloqui e ho fatto qualche ripasso tecnico. Devo dire che di offerte ce ne erano parecchie, i recruiter non hanno esitato a contattarmi e a farmi proposte. Ho sostenuto colloqui con due aziende, sono rimasto sorpreso da quanto erano tecnici e alla fine Autonomy Software Ltd mi ha fatto un’ottima proposta di lavoro essendo un neolaureato che ho deciso di accettare. Tuttavia questa multinazionale, qui in Gran Bretagna ha sede a Cambridge quindi mi sono dovuto trasferire. Anche in questo ambito sono state tante le piccole cose che mi hanno fatto crescere: parlare con i recruiter, i colloqui, il vestirsi in giacca e cravatta, le ore a cercare/filtrare le offerte, a personalizzare e scrivere le cover letter, nel frattempo sono anche riuscito ad aprire un conto in banca con HSBC e ad avere la mia carta di debito inglese, ad avviare le operazioni per ottenere il mio National Insurance Number.

Ricordo che Luca Minudel mi disse che l’idea di fare esperienza di lavoro all’estero e’ furba e che saro’ coinvolto in tante cose interessanti e nuove. Mi aveva detto anche che se sarei riuscito nella mia impresa di non scordarmi di condividere su UgiDotNet la mia esperienza, raccontare com'è, aiutare questa Italia a essere meno chiusa. Sono ben contento di farlo perche’ sono molto grato a questa community, ai rapporti umani che mi ha permesso di creare con persone che hanno la mia stessa grande passione. E sono sicuro che se sono riuscito ad arrivare dove sono e’ anche merito di tutti voi, di tutta questa passione che respiro ogni volta che leggo i vostri post. Pero’ a volte provo anche invidia, ma e’ quella positiva, quella di ammirazione, quella che ti spinge a crescere. Grazie a tutti ! Un grazie particolare anche ad Alessio Marziali che avendo gia’ vissuto certe esperienze si e’ offerto di fornirmi utili consigli e ovviamente grazie ai miei amici (Matteo, Marco e Mario) della community DotNetToscana che non hanno mai smesso di incitarmi e caricarmi in questa impresa.

Il mio primo giorno di lavoro e’ stato il 15 Febbraio. Nei giorni immediatamente precedenti la mia ragazza e’ venuta 5 giorni a Londra a trovarmi e per la prima volta dopo tre mesi sono riuscito a trovare il tempo di visitarla un po. Siamo andati al museo delle cere, tower hill, buckingham palace, camden town, Big Ban, Harrods, giro in battello sul Tamigi e London Eye di notte il giorno di San Valentino. Che si puo’ volere di piu’ dalla vita :) Ringrazio ovviamente anche a lei che ha seguito nei minimi dettagli tutta questa mia avventura e mi ha sempre supportato, nonostante la sua evidente sofferenza di non essere fisicamente vicina a me.

La mia prima settimana di lavoro e’ stata davvero intensa. Ho alloggiato in una casa offerta dall’azienda e nel poco tempo libero oltre il lavoro mi sono dovuto barcamentare di nuovo nella ricerca di una casa/appartamento a Cambridge. Sabato scorso, 20 Febbraio, ho finalmente trovato una bella sistemazione in una casa con tre persone, stanza molto spaziosa con bagno interno, Internet, sala con divani e televisore, cucina, insomma tutto il necessario. Anzi ancora meglio perche’ solamente 10 minuti a piedi dal Business Park dove lavoro, cosa che aumentera’ notevolmente la qualita’ della mia vita. Fermata dell’autobus quasi sotto casa che mi porta in centro in 15 minuti. Mi resta da comprare una bici e sono a posto! Quel giorno stesso sono tornato a Londra a prendere quasi tutta la mia roba (dovro’ fare un altro viaggio alla fine di questa settimana per completare il trasloco) e da ieri mi sono definitivamente spostato qui.

Ho ancora un po’ di cose da fare per completare il mio “trasloco di nazione”, tra cui ottenere il NIN, cambiare il medico di famiglia e iscrivermi all’associazione italiani residenti all’estero (AIRE).

Sicuramente mi sono dimenticato di racconare qualcosa, ma non ho dubbio nel dire che sono stati sicuramente i mesi piu’ intensi ed eccitanti della mia vita fino ad ora. Sono riusciuto a tagliare un traguardo difficile, a superare una sfida che volevo vincere. Sono contento di essere qui, sono sicuro che avro’ l’opportunita’ di crescere molto e sicuramente anche di riflettere molto. Non so cosa riservera’ il mio futuro, la mia ragazza spesso me lo chiede, ma purtroppo la vita non si puo’ prevedere. Non posso dire se tornero’ in Italia, non posso dire se mi sentiro’ solo, non posso dire se decidero’ di vivere qui per tanto tempo se non per sempre. Non posso dire niente, posso solo vivere. Quello che voglio ora e’ solamente una cosa: crescere professionalmente e imparare al massimo la lingua inglese. Ovviamente spero anche di divertirmi e farmi qualche nuovo amico.

E adesso?

Niente, direi di cominciare a vivere la mia nuova vita…

Posted by Angella Andrea

 

Questa mattina e’ arrivato il mio Amazon Kindle DX !!!! E’ veramente uno spettacolo !!!!

Ecco i principali vantaggi che cambieranno in meglio il mio modo di leggere:

  • Primo fra tutti lo schermo E-INK che e’ veramente come leggere su carta ! I miei occhi ringrazieranno.
  • Possibilita’ di viaggiare ovunque e portarmi con me la mia raccolta sterminata di libri, compresi quelli tecnici che potro’ consultare durante il lavoro
  • Schermo 9 pollici per fruire i contenuti al meglio (lo adoro)
  • Supporto nativo ai PDF. Ogni articolo sufficientemente lungo da ora in poi lo trasformero’ in PDF e me lo leggero’ sul Kindle. E gli occhi ringraziano di nuovo.
  • Anche il giornale (purtroppo di Italiani c’e’ solo “La Stampa”) arrivera’ ogni mattina con i contenuti aggiornati sul Kindle :)

Altri aspetti molto utili sono:

  • Possibilita’ in maniera molto semplice di sottolineare pezzi di testo
  • Possibilita’ di mettere segnalibri e aggiungere note testuali in qualsiasi punto (non possibile ovviamente per i PDF)
  • Dizionario di inglese in tempo reale. Basta spostarsi sulla parola con il cursore e appare in basso la definizione. Lo trovo utilissimo !!!
  • Dimensione del font variabiale.
  • Possibilita’ di acquistare libri ovunque grazie al Wireless
  • Supporto MP3 per ascoltare musica durante la lettura
  • Dicono durata della batteria notevole… vi sapro’ ridire

E’ tutto il pomeriggio che sto usando questo dispositivo e la prima impressione e’ stata davvero grande. Avevo grandi aspettative e sono state tutte mantenute. Un gioiello abbastanza costoso, ma ne vale la pena soprattutto per uno come me che adora leggere piu’ di ogni altra cosa.

Oggi in metropolitana a Londra dovevate vedere come la gente mi guardava, sussurrava: “ma quello e’ il Kindle di Amazon, waoo” e sbirciava. Considerate che Amazon ha iniziato le spedizioni dall’america solamente due giorni fa, il 19 Gennaio, quindi un certo stupore e’ normalissimo !!! Avrei fatto esattamente come loro oggi.

Sono certo che questo aggeggio sara’ uno dei miei migliori investimenti !

Posted by Angella Andrea

 

Oggi mi sono imbattuto in questa metrica. La Cyclomatic Complexity è una metrica non orientata agli oggetti, introdotta da Thomas McCabe, che misura la complessità strutturale di un metodo o un insieme di metodi.

Una possibile (banale) definizione è la seguente:

Cyclomatic Complexity (CC) = numero di punti di decisione (if, else, while, …) + 1

Il plugin per .NET Reflector chiamato CodeMetrics permette di calcolare questa metrica sia a livello di metodo che a livello di classe (tutti i metodi della classe).

Alcuni valori di complessità, giusto per curiosità:

  • CC della classe Uri = 1807
  • CC della classe DataTable = 1316
  • CC della classe DataSet = 618

Un valore troppo alto comporta una difficoltà nel testare una classe. Penso che sia proprio da un presupposto di questo tipo che da diverso tempo è nata la Campagna Anti IF per promuovere un utilizzo puro della OOP con lo scopo di realizzare applicazioni flessibili, modificabili e testabili.

Tra il dire e il fare c’è di mezzo il mare !

Per maggiori approfondimenti:
http://en.wikipedia.org/wiki/Cyclomatic_complexity
http://www.antiifcampaign.com/

Posted by Angella Andrea

 

Ora che ho terminato un bellissimo ma faticoso corso di inglese a Londra sto iniziando a cercare attivamente un lavoro nella capitale e nei dintorni. Molte aziende, per l’ammissione ai colloqui, chiedono la realizzazione di alcune applicazioni di test in modo da verificare se i candidati possiedono le conoscenze di base a loro necessarie. Considerato che ripassare è per me spesso un’operazione noiosa, e visto che sento la mancanza di scrivere sul mio blog, ho deciso di pubblicare in forma sintetica gli argomenti che sto rinfrescando senza la pretesa di essere esaustivo e senza l’obiettivo di creare guide chiare e lineari. Inizio con qualcosa di sicuramente noioso ma assolutamente necessario in ambito web e cioè i fogli di stile.

Introduzione


Le specifiche ufficiali “CSS livello 2 revisione 1” del W3C sono raggiungibili al seguente indirizzo: http://www.w3.org/TR/CSS2/

Sviluppare applicazioni web nel rispetto degli standard ha i seguenti vantaggi:

  • Compatibilità con un ampio numero di browser
  • Indipendenza dal dispositivo
  • Miglioramento dell’accessibilità dell’applicazione
  • Semplificazione dello sviluppo e della manutenzione del codice
  • Leggerezza del codice e quindi migliore velocità di navigazione
  • Migliore indicizzazione da parte dei motori di ricerca

Un foglio di stile è formato da un insieme di regole. Ogni regola è costituita da un selettore che specifica gli elementi a cui si fa riferimento e da un insieme di coppie proprietà-valori (dichiarazioni) che specificano come gli elementi selezionati devono essere rappresentati graficamente.

Le regole CSS possono essere scritte direttamente nel codice del documento XHTML all’interno del tag <style>

<head>
<style type=”text/css”>
/*<![CDATA[*/



/*]]>*/
</style>
</head>

oppure possono essere separate in fogli di stile esterni che possono essere collegati a una pagina attraverso il tag <link>

<head>
   <link rel=”stylesheet” href=”stile_esterno.css” type=”text/css” />
   …
</head>

 

Selettori


* è il selettore universale e seleziona ogni tipo di elemento dell’albero del documento.

p h1 h2 sono selettori di tipo e permettono di specificare regole che si applicano solamente ad un particolare tipo di elemento XHTML.

.classe è un selettore di classe che specifica una regola che può essere applicata ad un elemento utilizzando l’attributo class. Tramite l’attributo class è anche possibile applicare più classi contemporaneamente.

#elemento è un identificatore che permette di individuare un unico oggetto del documento con l’attributo id impostato. Non possono esistere due oggetti con lo stesso attributo id.

E’ possibile effettuare combinazioni come h1.classe e div#elemento.

Le pseudoclassi distinguono gli oggetti in base ad alcune loro proprietà intrinseche, quindi non richiedono una marcatura o una notazione particolare per essere specificate:

p:first-child individua il primo paragrafo.

a:link e a:visited si applicano rispettivamente ai collegamenti non visitati e visitati

a:hover, a:focus, a:active rispondono ad azioni compiute dall’utente come posizionamento del puntatore sopra un oggetto, la selezione e l’attivazione di un oggetto.

html:lang(it) differenzia gli elementi in base all’attributo lang.

Gli pseudoelementi selezionano una sottoparte di un elemento:

p:first-line seleziona la prima linea di un blocco, p:first-letter seleziona la prima lettera di un blocco.

Tramite i selettori di discendenza è possibile specificare i rapporti di parentela tra gli elementi:

body > p individua tutti i tag <p> direttamente contenuti nel tag <body> (figli)
body p individua tutti i tag <p> contenuti nel tag <body> indipendente dal grado di discendenza
h1 + p individua il primo tag <p> dopo <h1> (si chiama selettore fratello)

Tutti gli attributi possono essere utilizzati come selettori CSS utilizzando il selettore di attributi:

tag[att] verifica se l’attributo att è stato impostato
tag[att=val] verifica se l’attributo att assume uno specifico valore
tag[att~=val] verifica se l’attributo att assume come valore una serie di parole separate da spazi, una delle quali è esattamente val
tag[att|=val] verifica se l’attributo att assume come valore una lista di parole separata da un trattino, la prima delle quali è esattamente val

Classi e identificatori sono un caso particolare di selettore di attributo.

E’ possibile associare l’insieme delle dichiarazioni di una regola a più selettori contemporaneamente separandoli tramite una virgola come ad esempio h1, #id, p.classe { … }.

Quando due dichiarazioni sono in conflitto si applica la dichiarazione il cui selettore ha maggiore specificità.

 

Dichiarazioni


Lista delle proprietà per la specifica del font:

font-style: italic; 
font-weight: bold;
font-size: 90%;    
line-height: 2em;  
font-family : arial, helvetica, sans-serif;
text-align: justify;   

E’ possibile raggruppare gran parte delle proprietà nella proprietà font.

font: italic bold 2em/1.5em arial, helvetica, sans-serif;

Per inserire immagini di sfondo e colore di sfondo:

background-color: #FFCC99;
background-image : url (../immagini/sfondo.jpg);
background-repeat: no-repeat;
background-position: 20% 25%;

E’ possibile raggruppare gran parte delle proprietà nella proprietà background.

 

Il Box Model


Il Box Model è uno degli aspetti più importanti dei CSS poichè determina l’aspetto degli elementi a livello di blocco (<p>, <div>, <h1>…<h6>, <blockquote>).

Ogni box è caratterizzato da:

  • larghezza e altezza dei contenuti (proprietà width e height)
  • spazio tra contenuti e bordi (proprietà padding)
  • bordo (proprietà border)
  • spazio tra il bordo e gli altri oggetti della pagina (proprietà margin)

E’ possibile specificare le dimensioni minime e massime utilizzando le proprietà min-width, min-height e max-width, max-height.

La proprietà overflow (valori visible, hidden, scroll e auto) specifica cosa fare quando un elemento all’interno di un blocco supera in larghezza la dimenzione impostata per il box stesso.

La proprietà display (valori block, inline, list-item e none) permette di modificare il tipo di elemento.

Il tipo di posizionamento è definito attraverso la proprietà position e può essere static, relative, absolute o fixed. L’offset del posizionamento relativo è assegnato tramite le proprietà top, right, bottom e left che invece, nel caso di posizionamento assoluto, individuano la posizione del blocco. E’ possibile determinare la larghezza (altezza) di un blocco impostando contemporaneamente il valore delle proprietà left e right (top e bottom). Il posizionamento fisso è simile al posizionamento assoluto solamente che il riferimento per il posizionamento è sempre la finestra del browser e quando la pagina scorre, i blocchi rimangono ancorati alla posizione iniziale.

L’ordine di sovrapposizione dei blocchi può essere modificato utilizzando la proprietà z-index.

I blochi flottanti permettono la disposizione dei contenuti di blocchi successivi rispettivamente attorno al loro bordo destro o sinistro. Si utilizza la proprietà float con i possibili valori none, left, right. Un elemento flottante diventa implicitamente un elemento di blocco e viene estratto dal normale flusso della pagina. I margini di un box flottante non collassano. Per interrompere l’effetto del box flottante si può utilizzare la proprietà clear. Quando due blocchi flottanti sono disposti uno di seguito all’altro, si dispongono uno di fianco all’altro sulla stessa linea finchè c’è spazio disponibile.

Con la proprietà visibility (valori visible, hidden e collapse) è possibile regolare lo stato di visibilità di un elemento.

 

Il problema dei browser


La prima volta che ho studiato i CSS (più di 6 anni fa), in poche ore ho letto un manuale e ho compreso il significato dei vari attributi. Tutto contento inizio a fare alcune prove e mi accorgo di essere letteralmente imbranato e incapace di creare anche una delle più semplici interfacce. Mi chiesi: ma come è possibile ? La risposta era semplice: purtroppo ogni browser intepretava differentemente lo standard W3C e c’erano differenze notevoli di comportamento tra uno e l’altro. Tutto questo ha per molti anni limitato le potenzialità offerte dai CSS che dovevano per forza rimanere inespresse per mantenere la compatibilità tra browser differenti. Il peggiore di tutti, è doveroso dirlo è il browser Internet Explorer 6, che ha reso frustrante la vita di molti sviluppatori web !

Per fortuna oggi le cose sono notevolmente migliorate. Tutti i browser sostanzialmente offrono il supporto alla versione CSS 2.1 aprendo ai designer web nuove possibilità. Con la versione 8 di Internet Explorer finalmente anche Microsoft si è allineata agli standard. Quest’ultima versione supporta in modo completo tutta la versione 2.1 dello standard CSS e alcune caratteristiche presenti nella futura versione 3.

Voglio segnalare un link interessante e utile in cui è possibile verificare la compatibilità di un attributo CSS attraverso le varie versioni di Internet Explorer (che è il browser più diffuso): CSS Compatibiliy and Internet Explorer.

Posted by Angella Andrea

 

Ciao a tutti voi ragazzi di UgiDotNet, è davvero molto tempo che non scrivo su questo blog anche se ho sempre letto ogni singolo post pubblicato. Nell’ultimo anno sono stato molto occupato nel sostenere gli ultimi esami universitari, nel preparare la mia tesi di laurea e nel contribuire alla nascita e crescita di DotNetToscana.

In data 8 Ottobre 2009 ho finalmente completato il mio percorso di studi con risultati davvero eccezionali: 110 e lode con percorso di eccellenza !

Il video di presentazione e tutte le foto della cerimonia e della festa sono liberamente fruibili a questo indirizzo: http://picasaweb.google.it/angella.andrea/LaureaSpecialisticaEFesta#

E’ doveroso per me lodare le eccezionali capacità tecniche del mio relatore Tommaso Cucinotta, ricercatore della Scuola Superiore Sant’Anna di Pisa. Fanstastico notare che la sua homepage è suddivisa in due sezioni, quella “professionale” e quella “hobby & tempo libero”, e che in quest’ultima c’è scritto: “Il mio hobby preferito è da sempre l'informatica e la programmazione.”. Insomma è uno di quei pochi fortunati (o da alcuni punti di vista “fulminati”) ad amare veramente l’informatica e la programmazione tanto da occupare anche il suo tempo libero. Bhe io mi sento come lui e come molti iscritti a questo blog. Abbiamo costantemente “Sete di conoscenza”…. io ne ho davvero tanta !!!

La laurea rappresenta per me solamente il punto di partenza. Adesso che ho terminato il mio percorso formativo è ora finalmente di iniziare la mia crescita professionale. L’8 Novembre 2009 partirò per Londra e farò un corso di inglese super-intensivo di 6 settimane in Regent School. Vivrò in famiglia. Ho preso l’importante decisione di cercare lavoro a Londra iniziando quindi la mia esperienza professionale all’estero o almeno voglio provarci. Ultimamente sono stato molto più presente su Facebook rispetto a UgiDotNet, chi di voi mi conosce mi aggiunga pure alla lista degli amici.

Concludo facendo le mie più sincere congratulazioni a tutti i ragazzi che hanno ricevuto per la prima volta o che sono stati confermati nuovamente MVP.
Siete grandi e vi stimo tantissimo !!!

A presto

Posted by Angella Andrea

 

i love html HTML.it ha organizzato un gioco estivo su Facebook per promuovere il loro fantastico portale.
Si trattava di scrivere un breve testo in cui ogni utente spiegava le motivazioni per cui “ama” HTML.it.
I primi dieci che ottenevano più apprezzamenti vincevano una maglietta !!!

Sono tra i vincitori (terzo classificato)….niente di particolare, ma fa sempre piacere !

Qui la classifica definitiva dei vincitori:
http://www.facebook.com/home.php#/note.php?note_id=119827629084&ref=mf

 

Ciao a tutti

Posted by Angella Andrea

 

Ieri ho partecipato alla quarta UgiAlt.Net Conference a Bologna. E’ stata una giornata molto intensa, e i contenuti sono stati davvero molto interessanti.

In primis la sessione su Mono tenuta da Massimiliano Mantione. E’ stato veramente interessante conoscere i principali aspetti di Mono raccontati da un profondo conoscitore degli internals del framework. La sua enorme competenza tecnica che traspare evidente dalla sua sessione mi ha colpito tantissimo. Complimenti Massimiliano !!!

In secondo luogo è stato bello partecipare all’open space su Model View ViewModel con Mauro Servienti anche se non avevo ancora avuto modo di applicare questo pattern. E’ stupefacente la profonda conoscenza tecnologica di Mauro e il suo approccio estremamente pragmatico nell’affrontare i problemi. Ho seguito anche la sua ultima sessione di “UI Composition” ma devo ammettere che per quanto mi riguarda è un tema ancora troppo avanzato per me ma ho comunque colto le problematiche affrontate.

Anche la sessione di Roberto Valenti sulla sua esperienza nel refactoring di codice legacy è stata molto istruttiva e ha evidenziato una metodologia che può funzionare basata sull’analisi di metriche del codice e sull’applicazione più o meno sistematica di principi dell’OOP e del testing.

Infine la sessione su “Come progettare l’UX” di Daniela Panfili mi ha incuriosito in quanto ha offerto una prospettiva differente nel come può essere affrontato il problema di progettare interfacce grafiche separando il più possibile il lavoro dello sviluppatore da quello del grafico. Ero un pò scettico su questo aspetto ma l’esperienza di Daniela sembra dimostrare che spesso e volentieri l’approccio che ha presentato può funzionare e portare a una maggiore soddisfazione del cliente stesso forzandolo a scontrarsi fin da subito su tutti i possibili problemi di usabilità che lei chiamava “criticità”.

Andare a questi eventi è per me molto stimolante e mi fa rendere conto di quanta strada ancora devo fare nel fantastico mondo della programmazione. Inoltre è molto bello per me conoscere e rivedere persone che hanno la mia stessa passione.

Un sentito grazie a tutti gli organizzatori e agli ottimi speaker che hanno tenuto le varie sessioni della giornata.

A presto !

Posted by Angella Andrea


Novell ha completato la prima versione stabile di Moonlight.

Ecco qui il link alla notizia: http://punto-informatico.it/2549927/PI/News/moonlight-10-porta-silverlight-linux.aspx

Posted by Angella Andrea

Prima di tutto a voi ragazzi e ragazze di UgiDotNet:

Tanti auguri e felice 2009 !

Approfitto dell'occasione per segnalare a tutti che ho realizzato e pubblicato un nuovo articolo per la community di DotNetToscana.
Il titolo dell'articolo è "Introduzione al .NET Micro Framework".

Di seguito elenco le sezioni di cui è composto:

  1. Introduzione allo sviluppo su piattaforme embedded
  2. Che cos'è e perché è stato creato il .NET Micro Framework
  3. Versioni disponibili e caratteristiche principali
  4. Architettura del framework e Common Language Runtime
  5. Uno sguardo alla Base Class Library
  6. Come iniziare a sviluppare con il .NET Micro Framework
  7. Risorse utili per ottenere maggiori informazioni

Un saluto a tutti !

Posted by Angella Andrea

Su HTML.it è possibile trovare la traduzione in italiano dell'interessante intervista a John Resig che è il Team Leader del framework JQuery.

Può essere sicuramente interessante valutare l'acquisto del suo libro Pro Javascript Techniques e di un altro intitolato Secrets of the Javascript Ninja che sarà disponibile il prossimo anno.

Nel frattempo sono in attesa del libro JQuery in Action che sono molto curioso di leggere. Gian Maria è colpa tua :-)

 

jquery

Posted by Angella Andrea
Filed under:

Area di riferimento

- Implementing serialization and input/output functionality in a .NET Framework application (18 percent)
   - Compress or decompress stream information in a .NET Framework application and improve the security of application data by using isolated storage
      - May include but is not limited to: IsolatedStorageFile class, IsolatedStorageFileStream class;
      - DeflateStream class; GZipStream class


GZipStream and DeflateStream classes

La classi GZipStream e DeflateStream permettono di comprimere dati utilizzando il famoso algoritmo di compressione Gzip. Conviene utilizzare la classe GZipStream nel caso in cui si intenda distribuire i file in modo che questi possano essere decompressi utilizzando l'ampiamente diffuso tool gzip.

Queste classi si trovano nel namespace System.IO.Compression e il loro utilizzo è molto semplice.

class Program { static void Main(string[] args) { File.WriteAllText("source.txt", "Il contenuto di questo file verra' compresso."); // File compression using (FileStream sourceFile = File.Open("source.txt", FileMode.Open)) { using (FileStream destinationFile = File.Open("destination.dat", FileMode.Create)) { using (GZipStream comp = new GZipStream(destinationFile, CompressionMode.Compress)) { int b; while ((b = sourceFile.ReadByte()) != -1) { comp.WriteByte((byte)b); } } } } // File decompression using (FileStream sourceFile = File.Open("destination.dat", FileMode.Open)) { using (FileStream destinationFile = File.Open("new-source.txt", FileMode.Create)) { using (GZipStream decomp = new GZipStream(sourceFile, CompressionMode.Decompress)) { int b; while ((b = decomp.ReadByte()) != -1) { destinationFile.WriteByte((byte)b); } } } } Console.WriteLine(File.ReadAllText("new-source.txt")); Console.ReadKey(); } }

Isolated Storage

L'Isolated Storage è un repository all'interno del quale è possibile leggere e scrivere dati in maniera sicura indipendentemente dai privilegi di cui disponde il codice.

La prima cosa da fare quando si lavora con l'isolated storage è scegliere l'ambito in cui saranno memorizzati i dati:

  • Assembly/Machine : Si utilizza questo ambito per persistere dati a livello di applicazione.
  • Assembly/User : Si utilizza questo ambito per persistere dati a livello di utente. Ogni utente della macchina avrà le sue impostazioni specifiche.
  • ...

L'utilizzo dell'Isolated Storage ruota intorno alle classi IsolatedStorageFile e IsolatedStorageFileStream. E' inoltre possibile utilizzare l'attributo IsolatedStorageFilePermission per specificare il permesso di accedere all'Isolated Storage e impostare altri parametri come ad esempio la quota massima di spazio da associare a ciascun utente.

 

[IsolatedStorageFilePermission(SecurityAction.Demand, UserQuota=256)] class Program { static void Main(string[] args) { // Assembly/Machine Scope - Writing data IsolatedStorageFile applicationStorage = IsolatedStorageFile.GetMachineStoreForAssembly(); IsolatedStorageFileStream applicationStream = new IsolatedStorageFileStream("application-settings.dat", FileMode.Create, applicationStorage); using (StreamWriter writer = new StreamWriter(applicationStream)) { writer.Write("Informazioni a livello applicazione"); } // User/Machine Scope - Writing data IsolatedStorageFile userStorage = IsolatedStorageFile.GetUserStoreForAssembly(); IsolatedStorageFileStream userStream = new IsolatedStorageFileStream("user-settings.dat", FileMode.Create, userStorage); using (StreamWriter writer = new StreamWriter(userStream)) { writer.Write("Informazioni a livello utente in user-settings.dat"); } userStorage.CreateDirectory("folder"); userStream = new IsolatedStorageFileStream(@"folder\user-settings.dat", FileMode.Create, userStorage); using (StreamWriter writer = new StreamWriter(userStream)) { writer.Write("Informazioni a livello utente in folder\\user-settings.dat"); } // Reading data Console.WriteLine("Directories :"); foreach (string directory in userStorage.GetDirectoryNames("*")) { Console.WriteLine(directory); } Console.WriteLine("Files *.dat :"); foreach (string file in userStorage.GetFileNames("*.dat")) { Console.WriteLine(file); } Console.ReadKey(); } }

Area di riferimento

- Implementing serialization and input/output functionality in a .NET Framework application (18 percent)
   - Access files and folders by using the File System classes
      - May include but is not limited to: File class and FileInfo class; Directory class and DirectoryInfo class;
      - DriveInfo class and DriveType enumeration; FileSystemInfo class and FileSystemWatcher class; Path class;
      - ErrorEventArgs class and ErrorEventHandler delegate; RenamedEventArgs class and RenamedEventHandler delegate
   - Manage byte streams by using Stream classes
      - May include but is not limited to: FileStream class; Stream class; MemoryStream; BufferedStream class
   - Manage .NET Framework application data by using Reader and Writer classes
      - May include but is not limited to: StringReader class and StringWriter class; TextReader class and TextWriter class;
      - StreamReader class and Stream Writer class; BinaryReader class and BinaryWriter class


File System classes

Il framework .NET offre numerose classi che permettono l'accesso al file system.

La classe DriveInfo permette di ottenere informazioni relative ai drive presenti sulla macchina. La classe File permette di effettuare alcune tipiche operazioni sui file come la copia, la creazione e la cancellazione. Le classi FileInfo e DirectoryInfo derivano da FileSystemInfo e consentono di accedere a diverse informazioni relative a file e directory. Utilizzando queste classi inoltre è estremamente semplice navigare attraverso il file system ottenendo l'elenco dei file presenti all'interno di una directory e l'elenco di directory presenti all'interno di un'altra directory. La classe Path fornisce un valido supporto per estrapolare informazioni relative ad un path e soprattutto offre una comoda funzione per combinare due path fra loro.

Grazie all'interessantissima classe FileSystemWatcher è inoltre possibile monitorare in tempo reale le modifiche che vengono compiute all'interno di una particolare cartella semplicemente gestendo opportuni eventi.

Di seguito riporto un pò di codice che utilizza tutte queste classi. Il loro utilizzo è molto intuitivo per questo non ritengo necessaria alcuna ulteriore spiegazione.

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Console.WriteLine("Drive\n"); 6 7 DriveInfo driveInfo = new DriveInfo("C"); 8 Console.WriteLine("Name: {0}", driveInfo.Name); 9 Console.WriteLine("TotalSize: {0} bytes", driveInfo.TotalSize); 10 Console.WriteLine("TotalFreeSpace: {0} bytes", driveInfo.TotalFreeSpace); 11 Console.WriteLine("AvailableFreeSpace: {0} bytes", driveInfo.AvailableFreeSpace); 12 Console.WriteLine("DriveFormat: {0}", driveInfo.DriveFormat); 13 Console.WriteLine("DriveType: {0}", driveInfo.DriveType); 14 Console.WriteLine("VolumeLabel: {0}", driveInfo.VolumeLabel); 15 16 Console.WriteLine("\nFile:\n"); 17 18 File.AppendAllText("file1.txt", "Ciao a tutti da Andrea", Encoding.ASCII); 19 File.Copy("file1.txt", "file2.txt", true); 20 21 FileInfo file2Info = new FileInfo("file2.txt"); 22 Console.WriteLine("CreationTime: {0}", file2Info.CreationTime); 23 Console.WriteLine("LastWriteTime: {0}", file2Info.LastWriteTime); 24 Console.WriteLine("DirectoryName: {0}", file2Info.DirectoryName); 25 Console.WriteLine("Exists: {0}", file2Info.Exists); 26 Console.WriteLine("Extension: {0}", file2Info.Extension); 27 Console.WriteLine("FullName: {0}", file2Info.FullName); 28 Console.WriteLine("Name: {0}", file2Info.Name); 29 Console.WriteLine("IsReadOnly: {0}", file2Info.IsReadOnly); 30 Console.WriteLine("Length: {0}", file2Info.Length); 31 32 Console.WriteLine("\nDirectory:\n"); 33 34 DirectoryInfo dir2Info = file2Info.Directory; 35 Console.WriteLine("CreationTime: {0}", dir2Info.CreationTime); 36 Console.WriteLine("FullTime: {0}", dir2Info.FullName); 37 Console.WriteLine("Exists: {0}", dir2Info.Exists); 38 Console.WriteLine("LastAccessTime: {0}", dir2Info.LastAccessTime); 39 Console.WriteLine("LastWriteTime: {0}", dir2Info.LastWriteTime); 40 41 dir2Info.CreateSubdirectory("folder1"); 42 dir2Info.CreateSubdirectory("folder2"); 43 dir2Info.CreateSubdirectory("folder3"); 44 45 Console.WriteLine("Files in folder: "); 46 foreach (FileInfo fileInfo in dir2Info.GetFiles()) 47 { 48 Console.WriteLine("\t{0}", file2Info.Name); 49 } 50 51 Console.WriteLine("Directory in folder: "); 52 foreach (DirectoryInfo dirInfo in dir2Info.GetDirectories()) 53 { 54 Console.WriteLine("\t{0}", dirInfo.Name); 55 } 56 57 if (Directory.Exists("folder1")) 58 { 59 Directory.Delete("folder1"); 60 } 61 Directory.Delete("folder2"); 62 new DirectoryInfo("folder3").Delete(); 63 file2Info.Delete(); 64 65 Console.WriteLine("\nPath: c:\\prova\\file.txt \n"); 66 Console.WriteLine("GetDirectoryName: {0}", Path.GetDirectoryName(@"c:\prova\file.txt")); 67 Console.WriteLine("GetExtension: {0}", Path.GetExtension(@"c:\prova\file.txt")); 68 Console.WriteLine("GetFileName: {0}", Path.GetFileName(@"c:\prova\file.txt")); 69 Console.WriteLine("GetFileNameWithoutExtension: {0}", Path.GetFileNameWithoutExtension(@"c:\prova\file.txt")); 70 Console.WriteLine("GetFullPath: {0}", Path.GetFullPath(@"c:\prova\file.txt")); 71 Console.WriteLine("GetPathRoot: {0}", Path.GetPathRoot(@"c:\prova\file.txt")); 72 Console.WriteLine("GetRandomFileName: {0}", Path.GetRandomFileName()); 73 Console.WriteLine("GetTempPath: {0}", Path.GetTempPath()); 74 Console.WriteLine("GetTempFileName: {0}", Path.GetTempFileName()); 75 76 Console.WriteLine("Combine: {0}", Path.Combine("c:\\prova1", "prova2\\file.txt")); 77 78 Console.WriteLine("\nFileSystemWatcher: \n"); 79 80 Directory.CreateDirectory("folder"); 81 FileSystemWatcher fsWatcher = new FileSystemWatcher("folder"); 82 fsWatcher.Created += new FileSystemEventHandler(fsWatcher_Created); 83 fsWatcher.Deleted += new FileSystemEventHandler(fsWatcher_Deleted); 84 fsWatcher.Changed += new FileSystemEventHandler(fsWatcher_Changed); 85 fsWatcher.Renamed += new RenamedEventHandler(fsWatcher_Renamed); 86 fsWatcher.Error += new ErrorEventHandler(fsWatcher_Error); 87 88 fsWatcher.EnableRaisingEvents = true; 89 90 Console.ReadKey(); 91 } 92 93 static void fsWatcher_Error(object sender, ErrorEventArgs e) 94 { 95 Console.WriteLine("FileSystemWatcher Error\n"); 96 } 97 98 static void fsWatcher_Changed(object sender, FileSystemEventArgs e) 99 { 100 Console.WriteLine("ChangeType: {0}", e.ChangeType); 101 Console.WriteLine("FullPath: {0}", e.FullPath); 102 Console.WriteLine("Name: {0}\n", e.Name); 103 } 104 105 static void fsWatcher_Renamed(object sender, RenamedEventArgs e) 106 { 107 Console.WriteLine("ChangeType: {0}", e.ChangeType); 108 Console.WriteLine("FullPath: {0}", e.FullPath); 109 Console.WriteLine("Name: {0}", e.Name); 110 Console.WriteLine("OldFullPath: {0}", e.OldFullPath); 111 Console.WriteLine("OldName: {0}\n", e.OldName); 112 } 113 114 static void fsWatcher_Deleted(object sender, FileSystemEventArgs e) 115 { 116 Console.WriteLine("ChangeType: {0}", e.ChangeType); 117 Console.WriteLine("FullPath: {0}", e.FullPath); 118 Console.WriteLine("Name: {0}\n", e.Name); 119 } 120 121 static void fsWatcher_Created(object sender, FileSystemEventArgs e) 122 { 123 Console.WriteLine("ChangeType: {0}", e.ChangeType); 124 Console.WriteLine("FullPath: {0}", e.FullPath); 125 Console.WriteLine("Name: {0}\n", e.Name); 126 } 127 }

Streams

Gli stream realizzano un meccanismo unificato per gestire l'accesso sequenziale e random ai dati. La classe astratta Stream fornisce l'interfaccia di base e l'implementazione per tutti gli strem all'interno del Framework. Quando si apre un file viene restituito un oggetto di tipo FileStream che offre una interfaccia di basso livello per l'accesso al file. Le classi StreamReader e StreamWriter facilitano la lettura e la scrittura di file di testo. Le classi BinaryReader e BinaryWriter invece permettono la lettura e la scrittura di dati binari in modo più semplice del dover lavorare direttamente su vettori di byte.

Quando si lavora con piccoli file di testo è possibile utilizzare le funzioni File.WriteAllText e File.ReadAllText rispettivamente per scrivere un file di testo a partire da una stringa e per ottenere il contenuto di un file di testo all'interno di una stringa.

La classe MemoryStream fornisce le funzionalità per creare stream in memoria. Le classi StringReader e StringWriter invece svolgono le stesse funzionalità delle classi StreamReader e StreamWriter solo che la sorgente dati associata è una stringa al contrario di un file ( le classi astratte da cui derivano sono TextReader e TextWriter che implementano le funzionalità di base per la lettura e scrittura di testo).

Ecco un pò di codice dimostrativo:

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Console.WriteLine("*** Text Streams: ***\n"); 6 7 FileStream fs = File.Open("file.txt", FileMode.Create); 8 9 byte[] bytesTitolo = new ASCIIEncoding().GetBytes("Titolo del file\r\n\r\n"); 10 fs.Write(bytesTitolo, 0, bytesTitolo.Length); 11 12 using (StreamWriter sw = new StreamWriter(fs)) 13 { 14 sw.WriteLine("Ciao a tutti"); 15 sw.WriteLine("il mio nome è Andrea"); 16 } 17 18 using (StreamReader sr = File.OpenText("file.txt")) 19 { 20 while (!sr.EndOfStream) 21 { 22 Console.WriteLine(sr.ReadLine()); 23 } 24 } 25 26 Console.WriteLine(); 27 28 File.WriteAllText("file2.txt", "Prima riga del file2\r\nSeconda riga del file2"); 29 Console.WriteLine(File.ReadAllText("file2.txt")); 30 31 Console.WriteLine("\n*** Binary Streams: ***\n"); 32 33 fs = File.Open("file3.dat", FileMode.Create); 34 using (BinaryWriter bw = new BinaryWriter(fs)) 35 { 36 bw.Write('A'); 37 bw.Write(true); 38 bw.Write(12.45); 39 bw.Write("Ciao"); 40 } 41 fs = File.Open("file3.dat", FileMode.Open); 42 using (BinaryReader br = new BinaryReader(fs)) 43 { 44 Console.WriteLine(br.ReadChar()); 45 Console.WriteLine(br.ReadBoolean()); 46 Console.WriteLine(br.ReadDouble()); 47 Console.WriteLine(br.ReadString()); 48 } 49 50 Console.WriteLine("\n*** Memory Streams: ***\n"); 51 52 MemoryStream ms = new MemoryStream(); 53 using (StreamWriter sw = new StreamWriter(ms)) 54 { 55 sw.WriteLine("Scrivo su uno stream in memoria."); 56 sw.Flush(); 57 58 using (fs = File.Open("file.txt", FileMode.Append)) 59 { 60 ms.WriteTo(fs); 61 } 62 } 63 64 Console.ReadKey(); 65 } 66 }

Infine è importante citare la classe BufferedStream che permette di migliorare le performance implementando un meccanismo di lettura e scrittura bufferizzato.

Io, Andrea Angella, sono diventato un membro della community UgiDotNet il giorno 9 Agosto 2007 con il post Finalmente il mio blog tecnico. Circa un mese dopo alle ore 10:33 del giorno 11 Settembre 2007 (gli attentati fortunatamente non centrano niente) arriva nella mia casella di posta elettronica una mail da parte di Matteo Baglini.

Riporto il testo integrale di questa "storica" mail:

"Ciao,
girovagando per il tuo blog ho letto che studi a Pisa quindi non credo che abiti fuori Toscana, spero di non essere invadente ed antipatico, però ti volevo chiedere se hai letto della cena che sto organizzando a Livorno
http://blogs.ugidotnet.org/bmatte/archive/2007/09/06/cacciuccata-a-livorno-il-29-settembre.aspx. Ti va di venire? Se hai già letto l'annuncio e non sei interessato ti va di spiegarmi il perchè? Ti chiedo queste cose perchè ho visto che sono molto pochi i Toscani che hanno risposto all'appello e volevo capire il motivo, in modo da migliorare per un eventuale cena futura e perchè magari anche per questa. Ti chiedo ancora scusa per il disturbo e spero non essere stato scortese.

Ciao Matteo."

 

Ero molto felice di aver ricevuto quella mail ed ho accettato ben volentieri l'invito alla cena. Da quell'istante la mia presenza in UgiDotNet si è concretizzata, sapevo che quello sarebbe stato solo l'inizio di una serie di incontri che mi avrebbero permesso di conoscere personalmente persone eccezionali che condividono la mia forte passione per l'informatica e con le quali avrei potuto passare piacevoli momenti insieme per divertirsi, discutere e condividere esperienze. E così è stato...

La sera del 29 Settembre 2007 ho quindi partecipato alla prima cena con membri di UgiDotNet. Eravamo solamente in 4 (Io, Matteo Baglini, Igor Damiani e Omar Damiani) ma la serata è stata davvero molto piacevole. Verso mezzanotte i due fratelli Damiani (che ringrazio ancora per il forte spirito di community che mi hanno dimostrato) sono tornati a casa. Io avevo il treno verso le ore 3 quindi Matteo ha pensato di portarmi in un pub per fare quattro chiacchere. Dopo avermi presentato la ragazza (al contrario di me lui è felicemente fidanzato) e alcune sue amiche, non abbiamo resistito alla tentazione di tornare a parlare di .NET :-)

E' proprio lì che per la primissima volta abbiamo parlato della possibilità di costruire insieme una nuova community come punto di incontro di studenti e professionisti Microsoft presenti nella regione Toscana. I problemi erano tanti, in primis che eravamo pochi (la cena purtroppo era stata una triste conferma). Matteo pensava in grande, voleva fare le cose con i giusti tempi affinchè tutto non si rivelasse un fallimento, per questo prima di tutto voleva confrontarsi con altri ragazzi delle community regionali. Vedevo in lui una forte motivazione, un'estrema passione per il suo lavoro e soprattutto un incredibile spirito di community. logo_dotnet5

Il giorno 16 Ottobre 2008, ad un anno da quella data, ai Microsoft Days 2008 è stata ufficialmente presentata a Firenze la community DotNetToscana.

DotNetToscana è per sua volontà una associazione no-profit, dove non esistono ruoli ufficiali ma tutto evolve grazie alla passione di ciascun membro. Nonostante questo per me, Matteo Baglini è il Leader naturale del gruppo, colui che ha creduto e reso possibile tutto questo. Oggi è il compleanno di Matteo e questo post è il mio regalo per lui.

Il più grande augurio è che DotNetToscana possa crescere per diventare un punto di riferimento e sicuramente tutti i suoi attuali membri si impegneranno per questo.

Tanti auguri di Buon Compleanno Matteo !
Tanti auguri di Buon Inizio DotNetToscana !

Andrea

Posted by Angella Andrea

Questa mattina io e il mio collega Vincenzo abbiamo sostenuto l'esame di Informatica Industriale conseguendo entrambi una votazione pari a 30 e Lode !

L'esame consisteva (in parte) nella realizzazione del progetto di un semplice Sistema Embedded in modo da familiarizzare con la programmazione di microcontrollori. Abbiamo utilizzato il microcontrollore ADuC836 con un core a 8 bit (8052) e realizzato il software in linguaggio C.

Il risultato si chiama Speedy Finger ed è la realizzazione in hardware del semplice gioco del dito più veloce.

Di seguito il logo creato (ovviamente non realizzato da me che di grafica sono molto carente):

image

 

Per l'occasione (come richiesto dai docenti) abbiamo realizzato un video di presentazione disponibile su YouTube anche in alta risoluzione:

 

 

Oggi termina una lunga serie di progetti universitari che ho realizzato insieme a Vincenzo, collega ma soprattuto grande e sincero amico che ringrazio particolarmente per aver reso molto più piacevole (se non divertente) questo ultimo anno accademico.

Adesso personalmente cercherò di sostenere al più presto l'ultimo esame rimastomi per poi iniziare l'avventura della Tesi.

Posted by Angella Andrea

Area di riferimento

- Implementing serialization and input/output functionality in a .NET Framework application (18 percent)
    - Serialize or deserialize an object or an object graph by using runtime serialization techniques.
        - May include but is not limited to: Serialization interfaces; Serialization attributes; SerializationEntry structure and SerializationInfo class;
        - ObjectManager class; Formatter class, FormatterConverter class, and FormatterServices class; StreamingContext structure
   - Control the serialization of an object into XML format by using the System.Xml.Serialization namespace.
       - May include but is not limited to: Serialize and deserialize objects into XML format by using the XmlSerializer class; Control serialization by using serialization attributes;
       - Implement XML serialization interfaces to provide custom formatting for XML serialization; Delegates and event handlers provided by the System.Xml.Serialization namespace 
   - Implement custom serialization formatting by using the Serialization Formatter classes. 
       - May include but is not limited to: SoapFormatter; BinaryFormatter class


Serialization and Deserialization

La serializzazione consiste nel trasformare un oggetto in una sequenza di byte che può essere memorizzata o trasferita tra diverse applicazioni.

Affinchè un tipo possa essere serializzato è necessario decorarlo con l'attributo [Serializable]. Se non non si vuole serializzare un particolare membro allora si utilizza l'attributo [NonSerialized]. Nel caso fosse necessario eseguire del codice dopo l'operazione di deserializzazione (per esempio per impostare membri calcolati che non sono stati serializzati) si può implementare l'interfaccia IDeserializationCallback come mostrato nell'esempio.

1 [Serializable] 2 class Student : IDeserializationCallback 3 { 4 public Student(string name, string surname, DateTime birthDate) 5 { 6 Name = name; 7 Surname = surname; 8 BirthDate = birthDate; 9 calculateAge(); 10 } 11 12 public string Name { get; set; } 13 public string Surname { get; set; } 14 public DateTime BirthDate { get; set; } 15 16 [NonSerialized] 17 [SoapIgnore] 18 private int age; 19 20 public int Age 21 { 22 get 23 { 24 return age; 25 } 26 set 27 { 28 age = value; 29 } 30 } 31 32 public override string ToString() 33 { 34 return Name + ", " + Surname + ", " + BirthDate.ToShortDateString() + ", " + age; 35 } 36 37 private void calculateAge() 38 { 39 Age = DateTime.Now.Year - BirthDate.Year; 40 } 41 42 public void OnDeserialization(object sender) 43 { 44 calculateAge(); 45 } 46 }

Con la classe BinaryFormatter è possibile serializzare in modo efficiente l'oggetto ma questo sarà accessibile solo da parte di altre applicazioni .NET:

1 static void Main(string[] args) 2 { 3 Student student = new Student("Andrea", "Angella", new DateTime(1984, 7, 14)); 4 5 // Binary Serialization 6 using (FileStream fs = new FileStream("file.dat", FileMode.Create)) 7 { 8 BinaryFormatter bf = new BinaryFormatter(); 9 bf.Serialize(fs, student); 10 } 11 12 // Binary Deserialization 13 using (FileStream fs = new FileStream("file.dat", FileMode.Open)) 14 { 15 BinaryFormatter bf = new BinaryFormatter(); 16 student = (Student)bf.Deserialize(fs); 17 } 18 19 Console.Write(student); 20 Console.ReadKey(); 21 }

La classe SoapFormatter (assembly System.Runtime.Serialization.Formatters.Soap) permette di serializzare un oggetto come un SOAP Envelop adatto per essere condiviso anche con applicazioni non appartenenti al mondo .NET. Il suo utilizzo è analogo a quello della classe BinaryFormatter. E' possibile controllare la formattazione utilizzando opportuni attributi come [SoapAttribute], [SoapElement], [SoapEnum], [SoapIgnore] e [SoapInclude].

E' possibile serializzare un oggetto in uno specifico formato XML attraverso la classe XmlSerializer. Questa modalità ovviamente porta con se i vantaggi del linguaggio XML e cioè forte interoperabilità, amministrazione user-friendly e migliore compatibilità all'indietro. La serializzazione XML può serializzare solamente membri pubblici (al contrario di quella binaria) e non possono essere serializzati grafi di oggetti. E' richiesto un costruttore di default. Anche in questo caso è possibile personalizzare il markup xml che sarà generato utilizzando opportuni attributi come [XmlAttribute], [XmlElement], [XmlIgnore], [XmlEnum] ecc.

E' interessante la possibiiltà di generare classi con attributi xml a partire da un file XML Schema Definition. Lo strumento da utilizzare è il tool a linea di comando xsd.

Se si vuole avere un controllo maggiore sul processo di serializzazione e deserializzazione è possibile implementare l'interfaccia ISerializable. Tramite il metodo GetObjectData si specificano i membri che si vogliono serializzare. All'interno di un particolare costruttore (chiamato dopo la fase di deserializzazione) sarà possibile accedere a questi valori e ripristinare il contenuto dell'oggetto. E' possibile intervenire prima e dopo la fase di serializzazione e deserializzazione inserendo opportuni metodi decorati con gli attributi [OnSerializing], [OnSerialized], [OnDeserializing], [OnDeserialized]. La classe StreamingContext è utile se si vuole serializzare un oggetto in modo differente in base alla destinazione (stesso processo, processi su macchine differenti, ecc. ).

1 [Serializable] 2 public class Student : ISerializable 3 { 4 public string Name { get; set; } 5 public string Surname { get; set; } 6 public DateTime BirthDate { get; set; } 7 public int Age { get; set; } 8 9 // Costruttore standard 10 public Student(string name, string surname, DateTime birthDate) 11 { 12 Name = name; 13 Surname = surname; 14 BirthDate = birthDate; 15 calculateAge(); 16 } 17 18 // Costruttore per la deserializzazione 19 public Student(SerializationInfo info, StreamingContext context) 20 { 21 Name = info.GetString("Name"); 22 Surname = info.GetString("Surname"); 23 BirthDate = info.GetDateTime("BirthDate"); 24 } 25 26 [OnSerializing] 27 void BeforeSerialization(StreamingContext context) 28 { 29 // ... 30 } 31 32 [OnSerialized] 33 void AfterSerialization(StreamingContext context) 34 { 35 // ... 36 } 37 38 [OnDeserializing] 39 void BeforeDeserialization(StreamingContext context) 40 { 41 // ... 42 } 43 44 [OnDeserialized] 45 void AfterDeserialization(StreamingContext context) 46 { 47 calculateAge(); 48 } 49 50 public override string ToString() 51 { 52 return Name + ", " + Surname + ", " + BirthDate.ToShortDateString() + ", " + Age; 53 } 54 55 private void calculateAge() 56 { 57 Age = DateTime.Now.Year - BirthDate.Year; 58 } 59 60 #region ISerializable Members 61 62 // Metodo chiamato durante la fase di serializzazione 63 public void GetObjectData(SerializationInfo info, StreamingContext context) 64 { 65 info.AddValue("Name", Name); 66 info.AddValue("Surname", Surname); 67 info.AddValue("BirthDate", BirthDate); 68 } 69 70 #endregion 71 }

Anche se è raramente necessario è bene sapere che è offerta anche la possibilità di realizzare dei formatter personalizzati. Invece di utilizzare ad esempio la classe BinaryFormatter è possibile costruire il proprio formatter implementando l'interfaccia IFormatter o IGenericFormatter

More Posts Next page »