Technology Experience
My daily work

[Consulente, cronache] Problemi di mobilità

Tutte le mattine mi tocca affrontare l’ultimo tratto di A1 (Lodi-Melegnano), un lungo tratto di tangenziale Ovest (Melegnano-Assago) ed un ultimo pezzo di A7 (Assago-Famagosta), per cercare di raggiungere il parcheggio multipiano di Famagosta, da dove poi è possibile prendere la metropolitana M2, linea verde. Non sono un consulente che giro il mondo: ho un cliente e ho assunto quindi un modus-operandi efficiente e pulito.

Questo viaggio è in certi momenti piuttosto pericoloso: frenate improvvise, spostamenti di corsia scellerati, TIR in sorpasso, automobili che si immettono senza dare un minimo di precedenza, automobili che escono tagliando la strada, autoambulanze a sirene spiegate, furgoni blindati della polizia penitenziaria, nebbia, pioggia & neve. E’ circa dal 2001 che faccio questo tragitto, anche se – per dir la verità – in certi periodi esso ha subìto cambiamenti più o meno drastici. Nonostante questi pericoli, ai quali si può ovviare con un po’ di attenzione e di svegliezza al volante, alla fine ho raggiunto una conclusione: il fastidio ed il pericolo più grande è la completa incapacità di stimare con una certa accuratezza i tempi di percorrenza.

Così capita che un viaggio che di solito occupa 40-45 minuti, possa un giorno occupare 2 ore, o anche più. E senza spiegazione. E senza che i tabelloni luminosi siano in qualche modo d’aiuto. E così capita che un normale appuntamento alle 9:45 – orario normalmente accettabile – diventi motivo di ansia e di stress. E così può capitare di dover parcheggiare l’auto al piano superiore rispetto al solito perchè – e non ho mai capito perchè – se tu sei bloccato in coda, tutti gli altri arrivano comunque, in orario ed in ufficio. Come se tu arrivassi da un altro punto del pianeta. Forse è vero: ovunque io abbia lavorato negli anni passati, sono sempre stato l’unico ad arrivare da sud Milano. Pazienza.

La cosa ancora più interessante è quando poi si arriva in ufficio. Curioso, vado sul sito www.autostrade.it, nel tentativo di capire il motivo per cui sono arrivato in ufficio alle 10:20 invece delle 9:00. Seleziono la porzione d’Italia giusta, e sul sito mi appare una cartina che per cortesia ho riportato qui sopra. La ‘X’ non indica il punto dove scavare (cit.): indica Famagosta, il parcheggio di cui parlavo prima. La prima freccia (in basso a destra) indica la A1. L’altra freccia indica la tangenziale ovest. Il colore verde sulla A1 indica ‘tutto ok’: cosa verissima. Il colore ciano/azzurrino sulla ovest indica ‘dati non disponibili’. Uao, meraviglioso, utile. E nessun’altra pagina su www.autostrade.it spiega esattamente cosa sia successo.

Che bella la vita del consulente, costretto a combattere contro nemici invisibili. E costretti ad essere di cattivo umore.

Send to Kindle
.NET World

Da una embedded resource a IEnumerable<T> con Linq

Data la classe ContactFieldImport così implementata:

   1: public class ContactFieldImport
   2: {
   3:     public string Property { get; internal set; }
   4:     public string Field { get; internal set; }
   5:  
   6:     public ContactFieldImport() { }
   7:  
   8:     public ContactFieldImport(string property, string field)
   9:     {
  10:         Property = property;
  11:         Field = field;
  12:     }
  13: }

vogliamo creare una struttura IEnumerable<ContactFieldImport> popolata con una embedded resource definita nell’assembly locale.

Questa risorsa è un normale file di testo e contiene quanto segue:

FullName;Denominazione|
ManagerName;Titolare|
HomeAddress;Indirizzo|
HomeAddressPostalCode;CAP|
HomeAddressCity;Città|
HomeAddressState;Provincia|
Email1Address;Mail|
Body;Note|
CompanyName;RagioneSocialeFiscale|
BusinessAddress;IndirizzoFiscale|
BusinessAddressPostalCode;CapFiscale|
BusinessAddressCity;CittàFiscale|
BusinessAddressState;ProvinciaFiscale|
GovernmentIDNumber;PartitaIva|
OtherAddressCity;LuogoNascita|
OtherAddressCountry;Cittadinanza|
OrganizationalIDNumber;Matricola|

Ogni riga contiene una coppia Property/Field. Ho usato il pipe ‘|’ come separatore per le linee, e un ‘;’ per separare i due campi.

Possiamo farlo con Linq? Certo, con una piccola funzione come questa:

   1: private static void setupMappings()
   2: {
   3:     string mappingsFile = CoreServices.GetResourceContents("VivendoByte.MyProject.Core.ContactMapping.txt");
   4:     string[] lines = mappingsFile.Split('|');
   5:  
   6:     mappings = from l in lines
   7:                where (l.Length > 0)
   8:                let splitted = l.Split(';')
   9:                    select new ContactFieldImport
  10:                    {
  11:                        Property = splitted[0],
  12:                        Field = splitted[1]
  13:                    };
  14: }

La riga (3) restituisce tramite un metodo statico il contenuto della risorsa illustrata prima. Splitto le righe usando come separatore il carattere pipe ‘|’ (riga 4). Questa operazione di splitting restituisce un array di stringhe che – lo ricordiamo – è un oggetto interrogabile con Linq. Le righe 6-13 compongono una query Linq applicata su un string[]: filtro solamente le righe il cui .Length > 0, poi splitto e metto il risultato in un oggetto splitted. Per ogni riga restituisco un oggetto ContactFieldImport che va a popolare l’oggetto mappings dichiarato come IEnumerable<ContactFieldImport>.

Send to Kindle
Hardware

Se non riuscite a masterizzare un disco Dual Layer con Windows

Non lamentetevi con il sistema operativo, ma con l’hardware ed il firmware del vostro masterizzatore.

Questa è la regola, adesso vi spiego anche il perchè. Sul mio PC Desktop ho montato da anni un masterizzatore Dual Layer Philips DVDR 1640P. Il nome esatto l’ho letto tramite Windows, nella finestra delle Proprietà raggiunta da Risorse del Computer.

Non ho mai avuto problemi a masterizzare DVD da 4,7GBytes, il formato standard. Oggi pomeriggio ho dovuto per forza masterizzare un disco Dual Layer (DL), quelli cioè da 8,5GBytes. Qualche settimana fa ho acquistato on-line Dead Space, un videogame sci-fi horror, il cui setup, una volta scaricato in locale, occupa 7,40GBytes.

Beh, non c’era verso di riuscirci. Ci ho provato sia con Ashampoo Burning Studio, sia con Windows direttamente. Il DVD+R DL non veniva bruciato o perso irrimediabilmente, solo che la masterizzazione si interrompeva con errori ignoti e chiaramente il disco era vuoto.

Non volendo credere che fosse un problema puramente software, ho provato a cercare un aggiornamento per il firmware specifico per il mio modello. Aggiornamento che ho trovato a questo indirizzo. Ho scaricato lo zip, ho lanciato l’exe e ho aggiornato il firmware in pochi minuti. Poi ho riavviato il sistema e ho riprovato a masterizzare con le stesse impostazioni di prima.

Adesso è tutto ok. Masterizzare su un disco Dual Layer mi richiede quasi 50 minuti (2,4x), ma almeno lo fa!! Evvai.

Send to Kindle
.NET World

Qualche ragionamento su System.Reflection ed Interop con Outlook

In queste sere mi sto divertendo, se così si può dire, con la creazione di un plug-in per Microsoft Outlook 2007. Lo scopo è quello di importare nel folder Contacts di Outlook un’archivio di anagrafica, suddiviso in diverse categorie. Per farla breve vi faccio vedere solo due tabelle che illustrano il contenuto dell’anagrafica di cui sto parlando.

La tabella Tipi contiene la definizione delle categorie. Il campo “Tipo” contiene il nome della categoria (Cantanti, Gruppi, Discoteche, Pub, Feste in Piazza, etc.). Il campo “Lettera” contiene un singolo carattere (C, G, D, P, F, etc.) che indica con quale lettera è identificata una certa categoria; tale campo serve per andare in JOIN sulla tabella Anagrafica. In questo modo ogni record di Anagrafica appartiene ad una ed una sola categoria della tabella Tipi. Le relazioni mostrate nell’immagine qui sopra credo siano abbastanza chiare. Non accetto critiche sul database: l’ho ereditato io 10 anni fa su Access 2.0 e oggi gira in produzione su Access 2003 dopo tutti questi anni. Mi dovrei vergognare per questo? Forse sì, forse no, ma così è e così me lo prendo. 🙂

Comunque, lo scopo è quello di elaborare ogni record di Anagrafica e di creare un’istanza di Microsoft.Office.Interop.Outlook.ContactItem, popolandone tutte le proprietà pubbliche, e poi di salvarlo dentro Outlook 2007. Ecco uno stralcio di C# per dare l’idea:

1 foreach (MyDataSet.AnagraficaRow row in dataset.Anagrafica.Rows) 2 { 3 if (ContactAdding != null) ContactAdding(this, new ContactEventArgs(string.Empty)); 4 Outlook.ContactItem item = ContactServices.CreateContact(row); 5 6 if (item != null) 7 { 8 item.Save(); 9 if (ContactAdded != null) ContactAdded(this, new ContactEventArgs(item.FullName)); 10 } 11 }

Dato che si tratta di un prototipo mi sono semplificato la vita con un DataSet tipizzato. Ciclo su tutte le righe presenti nella DataTable. Per ogni riga sollevo due eventi ContactAdding e ContactAdded (ContactAdding e ContactAdded sono due public event, ContactEventArgs è una classe derivata da EventArgs). Ma il succo è la chiamata al metodo statico CreateContact, metodo che prende in input un’istanza di AnagraficaRow e restituisce un’istanza di ContactItem.

Tecnicamente parlando, possiamo implementare questo metodo in tanti modi diversi. Io ne ho pensati ed implementati due:

  1. assegno una ad una le proprietà pubbliche di ContactItem valorizzandole con i campi esposti da AnagraficaRow
  2. uso Reflection per fare qualcosa di più ingegnoso e gestibile nel prossimo futuro

Per il punto (1) il codice dovrebbe essere una cosa simile a questa:

1 ContactItem item = (ContactItem)folder.Items.Add(OlItemType.olContactItem); 2 if (!row.IsDenominazioneNull()) item.FullName = row.Denominazione; 3 if (!row.IsTitolareNull()) item.ManagerName = row.Titolare; 4 ... 5 ...

Alla riga (1) creo un’istanza di ContactItem, poi valorizzo le proprietà FullName, ManagerName e così via, per le decine di campi di cui necessitate (le mie sono 18). Noioso e davvero poco manutenibile.

Il punto 2 è più interessante, perchè tramite Reflection possiamo creare dinamicamente un’istanza di ContactItem. Creiamo una classe ContactFieldImport così implementata:

   1: public class ContactFieldImport
   2: {
   3:     public string Property { get; private set; }
   4:     public string Field { get; private set; }
   5:  
   6:     public ContactFieldImport(string property, string field)
   7:     {
   8:         Property = property;
   9:         Field = field;
  10:     }
  11: }

Ogni istanza di ContactFieldImport rappresenta una coppia di Property/Field. Possiamo così definire una List<ContactFieldImport>:

   1: List<ContactFieldImport> props = new List<ContactFieldImport>();
   2: props.Add(new ContactFieldImport("FullName", "Denominazione"));
   3: props.Add(new ContactFieldImport("ManagerName", "Titolare"));
   4: props.Add(new ContactFieldImport("HomeAddress", "Indirizzo"));
   5: props.Add(new ContactFieldImport("HomeAddressPostalCode", "CAP"));

Ogni coppia definisce come popolare un oggetto ContactItem. Prendo il valore del campo (Field) e con esso valorizzo la proprietà pubblica (Property) di ContactItem. A questo punto il gioco è semplice.

   1: foreach (ContactFieldImport cfi in props)
   2: {
   3:     PropertyInfo pi = typeof(_ContactItem).GetProperty(cfi.Property);
   4:  
   5:     if (pi != null && pi.CanWrite && !string.IsNullOrEmpty(row[cfi.Field].ToString()))
   6:     {
   7:         pi.SetValue(item, row[cfi.Field], null);
   8:     }
   9: }

Itero su tutti gli elementi contenuti nella lista props. Per ciascuno degli elementi, ottengo un riferimento alla PropertyInfo puntata da cfi.Property. Se la PropertyInfo è valida, può essere scritta (CanWrite == true) e se l’AnagraficaRow corrente è una stringa valida, allora imposto la proprietà dell’istanza di ContactItem (riga 7).

Dal punto di vista prestazionale, il ciclo for…each qui sopra è molto più veloce rispetto al primo metodo, quello che cioè che settava le proprietà pubbliche di ContactItem una ad una, senza una sorta di automatismo. Non so darvi con esattezza l’ordine di grandezza, ma ho provato ad importare con tutti e due i metodi qualcosa come 1.400 anagrafiche e tramite Reflection le cose erano molto migliori (< 1 minuto).

Il risultato finale visto in Outlook 2007 è il seguente:

Dentro Contatti ho creato un folder Winshow Planning (nome del progetto), all’interno del quale ho creato tre subfolders (Agenti, Artisti e Luoghi). In ciascuno dei tre ho finalmente creato tanti ulteriori subfolders (presi dal database). Ogni folder contiene i contatti assegnati ad ogni categoria.

‘Sto post è davvero troppo lungo e prolisso. Se avete domande, sono qua a disposizione. 😉

Send to Kindle
.NET World

Dubbi, ragionamenti e quiz sull’Interop di Outlook 2007

1 ContactItem item = (ContactItem)folder.Items.Add(OlItemType.olContactItem); 2 MemberInfo[] mi1 = typeof(ContactItem).GetMembers(); 3 MemberInfo[] mi2 = item.GetType().GetMembers(); 4 5 Console.WriteLine(mi1.Length); 6 Console.WriteLine(mi2.Length); 7 8 // m1.Length = 0 9 // m2.Length = 7

L’istanza item è di tipo ContactItem. Se chiamo GetMembers() sul GetType() di questa istanza ottengo un’array di mi1.Length.

Se chiamo GetMembers() sul typeof(ContactItem) ottengo un’array di mi2.Length.

Il primo array contiene 0 elementi. Il secondo array contiene 7 elementi. Difatti, indagando più a fondo:

// item.GetType() --> {Name = "__ComObject" FullName = "System.__ComObject"} // typeof(ContactItem) --> {Name = "ContactItem" FullName = "Microsoft.Office.Interop.Outlook.ContactItem"}

Qualcuno sa perchè? Vi è già capitato? Avete percorso la mia stessa strada con risultati diversi?

Send to Kindle
My personal life

Ludica al DatchForum di Assago

Ogni sera, quando me ne torno a casa, passo davanti al DatchForum di Assago. Ieri sera in particolare ho buttato l’occhio (adesso me ne è rimasto uno solo) e ho visto che questo weekend prenderà il via la prima edizione di Ludica, Festival Italiano del Gioco e del Videogioco. L’evento durerà dal 21 al 23 Novembre 2008 (da domani fino a domenica).

Di cosa si tratta? A guardare il sito, si parlerà di giochi, giochi in scatola, wargames, giochi per bambini e videogiochi. Gli sponsor sono molti. Qui cito Microsoft (per la parte hardware e per la XBox360), Ubisoft, Wizards Of The Coast (chi non ha sentito parlare di Dungeons & Dragons almeno una volta…scappi lontano), Intel, Hasbro, CoolMaster e molti altri ancora.

Ci sarà la possibilità di partecipare a tornei, a LAN Party, a provare console e videogiochi vari.

Il prezzo del biglietto intero è di 8 euro.

Maggiori informazioni sul sito ufficiale dell’evento.

Send to Kindle
.NET World

L’importanza di ereditare dall’applicazione giusta

Quando abbiamo imparato a programmare secondo la metodologia OOP, tutti, chi prima e chi dopo, abbiamo imparato che se ad esempio volessimo creare un nuovo controllo conviene ereditare da quello che più gli assomiglia ed implementare solo la parte richiesta. Quindi, se avessimo bisogno di una TextBox specializzata per lavorare con url, potremmo creare una classe UrlTextBox:

public class UrlTextBox : System.Windows.Forms.TextBox { }

E ancora, se avessimo bisogno di una Label particolare, mi potremmo creare uno UserControl che erediti da System.Windows.Forms.Label. E così via.

Una cosa di cui sento parlare poco negli ambienti virtuali che frequento è la possibilità di applicare lo stesso tipo di approccio anche con intere applicazioni, a patto che queste ‘intere applicazioni’ siano abbastanza amichevoli – passatemi il termine – per permettere a qualcun’altro di interagire con loro. Spesso noi programmatori abbiamo la tendenza a non pensare neanche ad una soluzione di questo tipo. Vogliamo partire completamente da zero nello sviluppo, più che altro per così sappiamo che avremo il pieno controllo di tutti gli strati applicativi.

Ora, lasciate che vi illustri uno scenario. Supponiamo di dover scrivere un’applicazione che fondamentalmente debba gestire un calendario. L’anagrafica è composta da artisti e locali. Il calendario conterrà appuntamenti, dove si esprime il fatto che un certo artista andrà in un certo locale in un certo periodo della giornata per cantare e ballare ed incassare tot euro. L’appuntamento avrà caratteristiche particolari: il compenso dell’artista, la sua provvisorietà o meno, l’agente, note varie, etc. etc. L’applicazione dovrà fornire all’utente una vista semestrale del calendario, artista per artista e locale per locale. L’applicazione dovrà avere un modulo di fatturazione, molti diversi tipi di report, e molto altro ancora.

Ma l’applicazione di cui sto parlando è fondamentalmente un calendario, al quale vengono applicate determinate restrizioni in alcuni casi. Quindi, mi stavo chiedendo, invece di scrivere tutto da zero, perchè non sfruttare ciò che già c’è. Perchè non partire da un’applicazione esistente, e restringere ciò che va ristretto, ed estendere ciò che va esteso? Perchè non scrivere una cosa del tipo…

public class MyApplication : Outlook { }

e lavorarci su con strumenti come Visual Studio Tools for Office ? Non è che si fa proprio così, ma è solo per rendere l’idea. Creare ribbon e toolbar, integrare plug-in capaci di fare tutto il necessario, capaci di incorporare al loro interno componenti realizzati con framework complessi come Windows Presentation Foundation.

Non è che le cose diventino pù semplici, magari fosse così, è solo che viene spostata la nostra attenzione, dal momento che l’applicazione host ci dà già alcuni servizi aggratis.

Meditate gente, meditate.

Send to Kindle
Software

Intelliremote è vivo più che mai

E’ davvero difficile riuscire a spendere 15 dollari USA per un piccolo software che ti possa essere davvero utile. Io credo proprio di esserci riuscito con Intelliremote, un software che – come scrissi diverso tempo fa – permette di poter sfruttare il proprio remote controller su PC per qualsiasi cosa, al di là dello scopo originario. Io ho preso un remote controller con la Sound Blaster Audigy, che mi permette di usare una versione ridotta di un Media Center.

Ma grazie ad Intelliremote riesco ad utilizzare il remote controller per tutte le cose che voglio: ACDSee, Powerpoint, Windows Media Player. Il pacchetto base comprende circa 30 profili che potete modificare a piacimento; in più potete crearvene di vostri in completa libertà.

I forum di Intelliremote sono attivi, e vengono rilasciati costantemente rilasciati aggiornamenti per migliorare la compatibilità dell’applicazione con i remote controller più nuovi (come quello della Wi).

Link : Sito Ufficiale Intelliremote

Send to Kindle
Community

Partecipazione ai Microsoft TechDays 2008

Ieri dopo tanto tempo ho partecipato ad un evento Microsoft. Agli scorsi Community Days, organizzati dall’amica UGIdotNET, non ho potuto partecipare per motivi di lavoro. Quindi ci tenevo ad essere presente ieri ai Microsoft TechDays 2008, non tanto per seguire le sessioni sulle ultime tecnologie Microsoft – cosa che comunque fa sempre bene – ma per ritrovare dopo qualche tempo vecchi e nuovi amici. Amici le cui facce vedo sempre su Facebook o sul mio Messenger, ma vederli di persona fa sempre un altro effetto.

Quindi, voglio salutare, in rigoroso ordine alfabetico, tutti quanti:

Daniele Armanasco, devi ringraziarti…ti ho conosciuto ieri e ti ho dato 10 anni in meno di quelli che hai!
Lorenzo Barbieri, ti ho ritrovato in grande forma…e un po’ più vicino a casa mia
Gianluca Carucci, uhm…visto l’ultima volta ad una cena in Liguria, penso… 🙂
Corrado Cavalli, ottima la tua sessione, ma non so quanti l’han percepita fino in fondo (io ti ho seguito i primi 59 minuti)
Alessandro Del Sole, che per sua stessa ammissione, ha mosso il primo passo (solo il primo!!) su WPF dai miei post 😉
Roberto Messora, visto che da un po’ di tempo non litighiamo più?
Matteo Migliore, ritrovato ancora – elegantissimo – con giacca & cravatta 😀
Andrea Saltarello, scusa per aver abbandonato la tua ultima sessione BOF, ma…avevo fame!!!
Alessandro Scardova, salutami Gigi e speriamo di vederci ad un prossimo evento dei tuoi 😉

Dedico una sezione staccata ai miei ex-colleghi: Paolo Boniolo, Massimo Longoni, Marcello Pusceddu, e – ultimo ma non ultimo – Massimo Solcia. Felice davvero di avervi ritrovato tutti assieme ad un evento come quello di ieri, dove abbiamo avuto anche qualche minuto per chiaccherare e ricordare i vecchi tempi pieni di database, stored-procedures, tuning, bla bla bla. Salutatemi tutti!

Tornando all’aspetto più tecnico della giornata di ieri, le sessioni diurne non mi hanno colpito più di tanto. Non per demerito degli speaker, sia chiaro, quanto perchè hanno comunque esposto concetti & framework di cui sono a conoscenza già da un po’. Mi ha interessato SQL Server 2008 e non mi è piaciuta la sessione su Silverlight 2, perchè era più che altro WPF. Avrei preferito un’evidenziazione dei concetti più specifici di Silverlight, le differenze con la sua controparte desktop, qualche peculiarità del mondo Web, etc. etc. Ma è solo il mio parere.

Le sessioni serali sono state – manco a farlo apposta – le migliori, le più divertenti e le più impegnative. Sapere su che piattaforma hardware/software gira la community UGIdotNET fa un certo effetto; sapere che genera 5 milioni di accessi al mese fa un altro effetto ancora. Colgo l’occasione per ringraziare Andrea per lo sbattimento e per l’impegno che ha messo per rimettere in piedi tutto. Vero che ormai da qualche tempo non bloggo più lì, ma il Muro di UGIdotNET comprende tutti gli amici di community. L’ultima sessione BOF l’ho dovuta voluta abbandonare per ‘evidente stato di fame’. Ho lasciato il fratello lì dov’era, mentre io mi sono unito a Lorenzo, Alessandro, Matteo e all’amico di Matteo per una bella pizzata in compagnia.

Ottima giornata, comunque, anche se siamo lontani dagli standard dettati dagli eventi di UGIdotNET.

Send to Kindle
My personal life

Bike Sharing a Milano, le cose si muovono

Finalmente pare proprio che il bike-sharing qua a Milano cominci ad attivarsi. Dal 28 Novembre il servizio dovrebbe essere attivo.

E’ stato attivato anche il portale http://www.bikemi.com, dove è possibile consultare la mappa delle stazioni disponibili, le tariffe e registrarsi come utenti.

Trovo la cosa molto interessante. Spostarsi all’interno di Milano in bicicletta può rivelarsi davvero comodo e veloce. La mappa sul portale sarà costantemente aggiornata, così sarà possibile sapere minuto per minuto dove trovare una bicicletta disponibile. Se al momento di lasciare la bicicletta si dovesse trovare una stazione completamente occupata, si avranno 15 minuti gratuiti per raggiungere la stazione più vicina. Le tariffe sembrano estremamente convenienti (25 Euro all’anno, 6 Euro alla settimana). Trovate una miriade di informazioni sul sito.

Divertente ed interessante! Lo proverò!!!

Send to Kindle