In occasione del lancio dei nuovi prodotti della serie 2008, Visual Studio, Sql Server e Windows Server, io e gli altri colleghi di XeDotNet saremo presenti per la nostra "Code Nigh Launch 2008". Si tratta di una serata in compagnia sulle tematiche del Framework 3.5. Ecco l'agenda dell'evento che seguirà il lancio:

Code Night Launch 2008 - 6 Marzo 2008

Sheraton Padova Hotel - Corso Argentina, 5 - Padova PD 35129, Italia

  • ore 19.00 Registrazione
  • ore 19.00 - 19.30 - HAPPY HOUR/DINNER
  • ore 19.30 - 20.00 - Ask the Expert
  • ore 20.00 - 21.00 - IEnumerable Tales: guida pratica per esempi all’uso di LINQ (Andrea Boschin)
  • ore 21.00 – 22.00 - Windows Live, integrazione in applicazioni reali (Davide Vernole)

Nella mia sessione, sulla quale sto lavorando alacremente vedremo assieme LINQ e cercheremo di trovare una chiave di lettura pratica che aiuti a integrarlo velocemente nelle nostre applicazioni. Appuntamento al 6 Marzo 2008.

Registrazione:


Le query expressions di C# 3.0 che di solito si usano per comporre le query di LINQ sono in realtà una facility che permette di ottenere una maggiore leggibilità del codice. Esse infatti vengono tradorre dal compilatore in una sequenza di chiamate ad Extension Methods che poi viene eseguita runtime.

Questo preambolo serve per introdurre in voi il dubbio che le query expressions abbiano qualche limite che possiamo superare facendo uso diretto dei metodi. Un esempio è dato dalla clausola "where" che a prima vista è esaustiva. Un esame più approfondito del relativo metodo Where() ci rivela che quest'ultimo ha due overload, e che solo uno dei due mappa direttamente la query expression. Il secondo metodo accetta come argomento una lambda expression che espone non solo l'elemento ma anche il suo indice nella collection.

Ecco un esempio di quello che possiamo fare:

   1: public static void Main(string[] args)
   2: {
   3:     var r1 = from name in stars
   4:              where name.StartsWith("Gamma")
   5:              select name;
   6:  
   7:     var r2 = stars.Where((name, index) => name.StartsWith("Gamma") && index % 2 == 0);
   8:  
   9:     Display(r1);
  10:     Console.WriteLine("**************************");
  11:     Display(r2);
  12:     Console.ReadLine();
  13: }

La variabile "stars" del mio esempio è un array di stringhe che contiene una serie di nomi di stelle. Per brevità l'ho omessa. Nell'esempio abbiamo che r1 viene valorizzato con una normale query expression mentre per r2 si fa uso del secondo overload di Where(). In questo modo si riesce a selezionare solo gli elementi pari. Si tratta di un esempio semplice, ma rivela che conviene approfondire bene lo strumento perchè ha dei risvolti nascosti che devolo essere rivelati.

Technorati Tag: ,

Poniamo di avere una collection di nostre custom entities che implementa IEnumerable<T> e poniamo di doverla ordinare rispetto ad una proprietà. Se ad esempio la entity rappresenta una riga ordine potremmo dover ordinare le righe per codice prodotto; con LINQ faremmo una cosa del genere:

   1: public void SortRowsBySKU(IEnumerable<OrderRow> rows)
   2: {
   3:     return from item in rows
   4:         orderby item.SKU ascending
   5:         select item;
   6: }

Linq è decisamente vantaggioso, e ci risparmia un bel po' di lavoro. Ma poniamo per un momento di dover ordinare ora la stessa collection per la proprietà Price, e magari dare all'utente la possibilità di scegliere la colonna a runtime. Ovviamente sarebbe una pessima idea creare una query per proprietà. Il codice diventerebbe inutilmente proolisso e poco manutenibile. Per parametrizzare la clausola di orderby potremmo invece usare la reflection come segue:

   1: public void SortRows(IEnumerable<OrderRow> rows, string sortExpression)
   2: {
   3:     return from item in rows
   4:         orderby item.GetPropertyValue(sortExpression) ascending
   5:         select item;
   6: }

Il metodo GetPropertyValue è un ExtensionMethod che viene da una classe di utilità relativa la reflection e semplicemente ottiene il valore di una proprietà di un oggetto passata come argomento di tipo stringa:

   1: public static class ReflectionExtensions
   2: {
   3:     public static object GetPropertyValue(this object value, string propertyName)
   4:     {
   5:         Type type = value.GetType();
   6:         PropertyInfo property = type.GetProperty(propertyName);
   7:         return property.GetValue(value, null);
   8:     }
   9: }

L'esempio in questione probabilmente è poco significativo perchè chiunque di voi avrà da obbiettare che sarebbe meglio fare l'ordinamento direttamente nella istruzione SQL che estrae i valori e io non posso che essere daccordo su questo. Ma sono certo che esistono un buon numero di casi in cui avendo a disposizione un semplice IEnumerable<T> sia necessario ordinarlo per una specifica proprietà. Mi raccomando però, questo esempio si applica solo a LINQ to objects.

Technorati Tag: ,

Era un po' di tempo che cercavo qualcosa di simile, ed ero quasi giunto alla conclusione di dover acquistare un account di Exchange e trasferire tutto (posta e calendari) su di esso. Oggi, ho finalmente trovato , una bella applicazione la cui versione base è freeware che mi consente di sincronizzare direttamente il calendario di Google con il mio PDA attraveso internet o via ActiveSync. L'applicazione fa uso del Compact Framework 2.0 e dalle prime prove che ho fatto sembra fatta proprio bene. Ora la proverò per qualche giorno e se fa al caso mio potrei anche investire i 30$ annui per la versione pro, sempre che ne senta il bisogno.

Download e info:

Technorati Tag: , ,

Da qualche tempo in rete proliferano gli Extension Methods. Lo stesso Scott Guthrie in un suo recente ne ha presentato uno, e qualcun altro ne ha preparato addirittura una . Queste utili estensioni che tipicamente si applicano ai tipi del Framework per estendere le funzionalità, aggiungendo magari qualcosa che chi ha progettato una classe non poteva certo prevedere.

Questo cappello serve ad introdurre il mio contributo a questa moda... :). Pochi minuti fa, mentre portavo un po' di codice verso il Framework 3.5, m'è venuto in mente di trasformare un in Extension Method. Il bello è che il "porting" ho richiesto la semplice introduzione della parola chiave "this" davanti al primo parametro, quindi non più di 30 secondi netti considerando anche il refactoring delle due posizioni in cui il metodo era usato e un misunderstanding con l'intellisense di Resharper che ancora non li supporta. Ecco il risultato:

public static class ControlUtil { /// <summary> /// Finds the control recursive. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="root">The root.</param> /// <param name="id">The id.</param> /// <returns></returns> public static T FindControlRecursive<T>(this Control root, string id) where T : Control { if (root.ID == id && root is T) return root as T; if (root.HasControls()) { foreach (Control child in root.Controls) { T foundControl = FindControlRecursive<T>(child, id); if (foundControl != null) return foundControl; } } return default(T); } }

Il "this" in questione è quello situato davanti al primo parametro del metodo che conferisce ad esso la capacità di essere usato anche come Extension Method (l'uso consueto rimane sempre possibile però...).

Ora, scritto questo e compilato referenziando l'assembly System.Core.dll, diventa possibile scrivere qualcosa del genere:

... public partial class DefaultPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { TextBox txtCode = this.FindControlRecursive<TextBox>("txtCode"); } } ...

In pratica con gli Extension Methods è possibile avere il meglio della programmazione Object Oriented, ma anche la possibilità di estendere le classi create da altri senza per questo violare il principio dell'incapsulamento... Parafrasando un noto spot pubblicitario si potrebbe dire: "è come avere la moglie che dice sempre sì..."

Sto bene... Sto Benissimo!!!

Technorati tags: , ,

Giusto ieri, mentre cercavo di approfondire i concetti di WCF per questioni di lavoro, mi sono scontrato con il supporto che WCF da a WS-Atomic Transaction. Il problema di fondo è che sostanzialmente non riuscivo a farle funzionare, fintanto che mi sono accorto che nella documentazione è riportato che bisogna abilitare DTC (Distributed Transaction Coordinator) a questo supporto per poter utilizzare il protocollo in WCF.

Ora... l'abilitazione in questione non è esattamente immediata, ed ecco il motivo di questo mio post. Innanzitutto, se provare ad eseguire la linea di comando che viene fornita nella documentazione vi troverete di fronte ad un bel problema: il framework 3.0 deve essere patchato con una hotfix per poter poi procedere a questa abilitazione. La hotfix è disponibile per diverse piattaforme a questo indirizzo:

Una volta installata la patch occorre munirsi di un certificato valido. Io ho utilizzato con facilità uno di quelli che si trovano nei tanti esempi. A questo punto esistono due modi per effettuare l'abilitazione. Il primo usa wsatconfig.exe e richiede l'uso del prompt dei comandi:

wsatconfig.exe –network:enable –port:443 –endpointCert:<machine|"Issuer\SubjectName"> -accountsCerts:<thumbprint|"Issuer\SubjectName"> -restart

Per i più pigri, che non hanno voglia di digitare tutta questa stringa esiste nel SDK di Windows un addin per la Management Console che abilita una tabella WS-AT all'interno della configurazione dei Component Services. Semplicemente andate nelle cartelle dell'SDK e cercate wsatui.dll dal prompt dei comandi. Quando ci siete digitate:

regasm /codebase wsatui.dll

Una volta registrato potrete andare nella MMC e troverete il nuovo tab al suo posto dalle proprietà di My Computer. Il tab sarà completamente disabilitato fintanto che non avrete abilitato Network DTC Access. Per procedere all'abilitazione fare così:

1) aprite Componente Services > Computers > My Computer

2) scegliete il tab MSDTC

3) selezionate "Security Configuration"

4) abilitate il check "Network DTC Access"

5) abilitate i check "Allow Inbound" e "Allow Outbound"

6) assicuratevi che nel campo Account sia impostato "NT Authority\NetworkService"

A questo punto siete pronti per abilitare il DTC e comnciare ad usare WS-Atomic Transaction


Chi si è cimentato nel parsing di HTML mediante regular expressione probabilmente ha sbattuto contro il seguente problema:

Poniamo ad esempio di fare il match di una coppia <td></td> in una tabella come la seguente:

   1: <table>
   2:     <tr>
   3:         <td>Cella1</td>
   4:         <td>Cella2</td>
   5:     </tr>
   6: </table>

Potremmo usare una regular expression siffatta:

MatchCollection matches = Regex.Matches(@"<td>.*</td>");

Purtroppo il risultato è diverso da quello che ci si può aspettare. Infatti il motore di risoluzione delle regular-expressions in .NET così come in molti altri linguaggi è ottimistico e tenta sempre di effettuare il match più largo possibile. Perciò il risultato del precedente pattern è:

1: <td>Cella1</td><td>Cella2</td>

(il numero indica la quantità di match in MatchCollection)

Per ottenere un matching "non-greedy" (letteralmente non-ingordo) cioe esattamente quello che ci si sarebbe aspettato è necessario modificare il pattern introducendo un ? dopo il carattere che quantifica le ripetizioni:

MatchCollection matches = Regex.Matches(@"<td>.*?</td>");

Ed ecco che il risultato diventa

1: <td>Cella1</td>
2: <td>Cella2</td>

Fonte:


Stamane abbiamo scoperto con il collega , che se si prova a fare una ParseExact in cultura tedesca (de-DE) di una data "25/05/2007" con il formato "dd/MM/yyyy" l'operazione fallisce con l'errore "String was not recognized as a valid DateTime". Dopo vari esperimenti e dopo aver reperito un in lingua tedesca che mi ha messo un tarlo ho trovato la soluzione che implica l'uso di forma di questo tipo: "dd\/MM\/yyyy". A quanto pare lo slash in tedesco ha un significato particolare e richiede di essere protetto da un backslash. Ecco uno snippet:

   1: using System;
   2: using System.Globalization;
   3: using System.Collections.Generic;
   4:  
   5: public class MyClass
   6: {
   7:     public static void Main()
   8:     {
   9:         string date = "25/05/2007";
  10:         
  11:         Console.WriteLine(date);
  12:         
  13:         try
  14:         {    
  15:             DateTime result = DateTime.ParseExact(date, @"dd\/MM\/yyyy", CultureInfo.CreateSpecificCulture("de-DE"));
  16:             Console.WriteLine(result.ToString());
  17:         }
  18:         catch(Exception ex)
  19:         {
  20:             Console.WriteLine(ex.Message);
  21:         }
  22:                 
  23:         RL();
  24:     }
  25:     
  26:     #region Helper methods
  27:  
  28:     private static void WL(object text, params object[] args)
  29:     {
  30:         Console.WriteLine(text.ToString(), args);    
  31:     }
  32:     
  33:     private static void RL()
  34:     {
  35:         Console.ReadLine();    
  36:     }
  37:     
  38:     private static void Break() 
  39:     {
  40:         System.Diagnostics.Debugger.Break();
  41:     }
  42:  
  43:     #endregion
  44: }

Appena riesco a capire il motivo esatto vi so dire


Un post veloce a questa strana ora del giorno per segnalarvi un paio di link che legano tra loro Visual Studio 2005 e Powershell. I primi sono due link dove si possono scaricare dei template di progetto per creare cmdlets in Visual Studio 2005:

Il secondo, dal mio punto di vista molto più utile riguarda l'uso di Powershell al posto del Command Prompt di Visual Studio 2005.

 


Sul sito di MSDN è stato pubblicato un libro gratuito a proposito di Security. Ovviamente nn ho ancora fatto a tempo a leggerlo, ma da una prima scansione veloce il libro, che conta 147 pagine, pare fatto bene.

Il libro viene illustrato come segue:

These security engineering activities have been developed by Microsoft patterns & practices to build on, refine and extend core lifecycle activities with a set of security-specific activities. These include identifying security objectives, applying design guidelines for security, threat modelling, security architecture and design reviews, security code reviews and security deployment reviews.

Se siete interessati potete scaricarlo gratuitamente da qui:


Vi confesso che non vedo l'ora di poter ascoltare Davide Bedin al prossimo meeting di XeDotNet. Da oggi sono aperte le iscrizioni per la data del 6 aprile 2007 e chiunque può dare la propria adesione all'evento direttamente nel sito Microsoft.

Come al solito i posti sono limitati perciò vi invito a dare la vostra adesione in fretta per evitare di perdere l'occasione, ma anche di cancellare la vostra adesione qualora qualcosa vi impedisca di partecipare.

Davide che so alacremente impegnato a prepararsi, ci presenterà Windows Communication Foundation, piattaforma per cui la sua azienda è segnalata, unica italiana, tra quelle che l'hanno adottata con largo anticipo. Ci sarà davvero molto da imparare.

Link: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032334359&Culture=it-IT


Ho scoperto un paio di post di , risalenti a Luglio e Settembre scorso che spiegano come evitare i problemi di lentezza nella compilazione dei progetti Web di Visual Studio 2005. In particolare nel mio caso ho risolto quello che Scott chiama "Dueling Assembly Reference" che mi obbligava ad attendere quasi due minuti la compilazione di una soluzione con solo 15 progetti. Se per caso anche a voi il compilatore pare soffermarsi un po' troppo nella fase di "Validating Web Site", è probabilmente venuto il momento di applicare il workaround descritto nei post linkati qui sotto.