<?xml version="1.0" encoding="iso-8859-15"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"><channel><title>blogs.ASPItalia.com</title><link>http://blogs.aspitalia.com//ricciolo//</link><description>blogs.ASPItalia.com</description><language>it-it</language><copyright>1998-2012 ASPItalia.com/blogs.ASPItalia.com</copyright><generator>Generated by feed.ASPItalia.com 'Cortana' 2012.1.31</generator><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><sy:updateBase>1998-01-01T12:00+00:00</sy:updateBase><lastBuildDate>Thu, 10 Nov 2011 20:32:00 GMT</lastBuildDate><image><title>blogs.ASPItalia.com</title><url>http://gui.aspitalia.com/images/aspitalia/syndication.gif</url><link>http://blogs.aspitalia.com//ricciolo//</link></image><item><title>ASPItalia.com sulla strada verso Windows 8</title><link>http://blogs.aspitalia.com/ricciolo/post2718/ASPItalia.com-Strada-Windows.aspx</link><pubDate>Thu, 10 Nov 2011 20:32:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2718" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Fornita la&lt;strong&gt; Developer Preview di Windows 8&lt;/strong&gt;, non si può resistere alla tentazione di provare e testare le &lt;strong&gt;WinRT&lt;/strong&gt; e &lt;strong&gt;Visual Studio 2011&lt;/strong&gt;.&amp;#xa0;Il&amp;#xa0; nostro gruppo lo sta&amp;#xa0;facendo con qualcosa di pratico&amp;#xa0;che ormai è diventato&amp;#xa0;la nostra palestra di sviluppo: l'applicazione client di ASPItalia.com.&lt;/p&gt;&lt;p&gt;Dopo averla sviluppata per &lt;strong&gt;Windows Phone 7&lt;/strong&gt; con le tecniche e i framework in cui crediamo abbiamo deciso di cominciare un cammino di porting anche verso &lt;strong&gt;Metro&lt;/strong&gt;. C'è da dire che la facilità e il riutilizzo delle proprie conoscenze sono un grosso punto a favore ed è bastato poco per vedere già dei risultati. Eccoli:&lt;/p&gt;&lt;p&gt;&lt;a href="http://blogs.aspitalia.com/img/Ricciolo/aspitaliaMetroBig.png"&gt;&lt;img src="http://blogs.aspitalia.com/img/Ricciolo/aspitaliaMetroSmall.png" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Io e &lt;a href="http://blogs.aspitalia.com/daniele"&gt;Daniele&lt;/a&gt;, in occasione di &lt;a href="http://www.wpc2011.it/"&gt;WPC 2011&lt;/a&gt;, metteremo a disposizione la nostra esperienza nella &lt;a href="http://www.wpc2011.it/sessions.aspx?sId=89#"&gt;sessione&lt;/a&gt; che terremo. Vi invitiamo quindi a partecipare, perché sarà molto interessante.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.5/" rel="tag"&gt;.NET Framework 4.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Metro/" rel="tag"&gt;Metro&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/WinRT/" rel="tag"&gt;WinRT&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2718/ASPItalia.com-Strada-Windows.aspx"&gt;&lt;em&gt;ASPItalia.com sulla strada verso Windows 8&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Metro Style app, .NET Framework, .NET Framework 4.5, Metro, WinRT</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2718/ASPItalia.com-Strada-Windows.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2718/ASPItalia.com-Strada-Windows.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2718.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2718</trackback:ping></item><item><title>Prestazioni delle query LINQ in architetture complesse</title><link>http://blogs.aspitalia.com/ricciolo/post2705/Prestazioni-Query-LINQ-Architetture-Complesse.aspx</link><pubDate>Mon, 30 May 2011 09:39:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2705" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;

In un &lt;a href="http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx"&gt;post precedente&lt;/a&gt; ho parlato dell'interfaccia &lt;strong&gt;IQueryable&lt;/strong&gt; e dell'utilità che può avere se passata tra i vari strati dell'applicativo, dal repository fino ai servizi applicativi. La tecnica è molto comoda ed elegante, ma comporta alcuni problemi, uno dei quali è la scelta delle navigation property da materializzare, che per l'appunto ho risolto con una tecnica illustrata nel post menzionato.&lt;/p&gt;&lt;p&gt;Nell'esperienza da me fatta mi sono però un giorno ritrovato con una query dalle prestazioni davvero scadenti.&amp;#xa0;La query in questione&amp;#xa0;impiegava &lt;strong&gt;6 secondi&lt;/strong&gt; per ottenere una sola entità con molteplici navigation property da caricare perciò subito ho dato la colpa a SQL Server. Guardo la query TSQL con SQL Profiler, la eseguo e noto con sorpresa che su SQL Sever essa viene eseguita in un istante, perciò ripiego su Entity Framework che, sebbene i dati non siano tanti, impiega molto tempo nell'analisi della view e nella preparazione della query. Faccio quindi un test compilando la query con la classe &lt;strong&gt;CompiledQuery&lt;/strong&gt;,&amp;#xa0;come da best practice, e ottengo così prestazioni ottime. Il problema è che in una soluzione a strati, le query compilate non si possono usare, perché solo chi consuma i dati conosce la query managed e la dovrebbe compilare, ma così facendo si accoppierebbe al tipo di repository. La prima soluzione che ho pensato è di creare metodi specifici sull'interfaccia di repository, tipo &lt;em&gt;&amp;quot;DammiOrdineConDettaglioECliente&amp;quot;&lt;/em&gt;, perdendo però i benefici di IQueryable e creando operazioni ripetitive. Ho quindi cercato un'altra strada riprendendo la stessa tecnica dell'extension method include.&lt;/p&gt;&lt;p&gt;Sempre nel post precedente ho mostrato come possiamo metterci in mezzo, tra la query ed &lt;strong&gt;Entity Framework&lt;/strong&gt;, per manipolarla prima che venga passata al motore. Ho applicato quindi lo stesso concetto intervenendo anche in questo caso sull'interfaccia &lt;strong&gt;IQueryProvider&lt;/strong&gt;. Ipotizzando di avere una query tipo:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;int&lt;/span&gt; n = 1;
customers.Where(c =&amp;gt; c.Orders.Count &amp;gt; n)&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;l'idea è quella di intervenire prima di eseguirla e di:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;renderla generica in modo da essere indipendente da variabili e parametri;&lt;/li&gt;&lt;li&gt;guardare in cache se è presente il delegate oppure compilare la query;&lt;/li&gt;&lt;li&gt;invocare la funzione passando le variabili e i parametri.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Per il primo passaggio uso un expression visitor anche in questo caso che trasforma la query precedente in questa:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;Convert(Param_0.Customers).Where(c =&amp;gt; (c.Orders.Count &amp;gt; Param_1))&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Come si vede, la query è stata&amp;#xa0;parametrizzata per accettare&amp;#xa0;l'&lt;strong&gt;ObjectContext&lt;/strong&gt; e il valore di confronto&amp;#xa0;che è esterno alla query (la variabile n).&amp;#xa0;A questo punto uso il ToString dell'expressione stessa, come chiave per fare lookup su un dizionario di chiave/delegate. Se non lo trovo&amp;#xa0;uso la classe CompiledQuery, individuo il metodo adatto per il numero di parametri generici da passare, compilo la query e salvo il delegate nel dizionario. Per farvi capire, di seguito il codice che uso per la compilazione:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;
&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; Delegate Compile(IEnumerable&amp;lt;ParameterExpression&amp;gt; parameters, Type returnType)
{
  &lt;span style="color:#008000"&gt;// Preparo i parametri della lambda mettendo in coda il tipo ritornato&lt;/span&gt;
  Type[] types = parameters.Select(p =&amp;gt; p.Type).Concat(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Type[] { returnType }).ToArray();

  &lt;span style="color:#008000"&gt;// Ottengo il tipo di delegate&lt;/span&gt;
  Type funcType = Type.GetType(String.Format(&amp;quot;&lt;span style="color:#8B0000"&gt;System.Func`{0}, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/span&gt;&amp;quot;, types.Length));
  &lt;span style="color:#0000FF"&gt;if&lt;/span&gt; (funcType == &lt;span style="color:#0000FF"&gt;null&lt;/span&gt;)
    funcType = Type.GetType(String.Format(&amp;quot;&lt;span style="color:#8B0000"&gt;System.Func`{0}, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089&lt;/span&gt;&amp;quot;, types.Length), &lt;span style="color:#0000FF"&gt;true&lt;/span&gt;);
  funcType = funcType.MakeGenericType(types);

  &lt;span style="color:#008000"&gt;// Creo la lambda in base al tipo&lt;/span&gt;
  var lambda = Expression.Lambda(funcType, expression, parameters);

  &lt;span style="color:#008000"&gt;// Chiamo il metodo compile specifico&lt;/span&gt;
  MethodInfo method = &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(CompiledQuery).GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
    .FirstOrDefault(n =&amp;gt; n.Name == &amp;quot;&lt;span style="color:#8B0000"&gt;Compile&lt;/span&gt;&amp;quot; &amp;amp;&amp;amp; n.IsGenericMethod &amp;amp;&amp;amp; n.GetGenericArguments().Length == types.Length);
  Delegate compiledFunction = (Delegate)method.MakeGenericMethod(types).Invoke(&lt;span style="color:#0000FF"&gt;null&lt;/span&gt;, &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; &lt;span style="color:#0000FF"&gt;object&lt;/span&gt;[] { lambda });

  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; compiledFunction;
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A questo punto devo invocare il delegate, perciò riprendo i parametri della query corrente da eseguire e li passo al delegate, ottenendo così il risultato.&lt;/p&gt;&lt;p&gt;Così facendo metto dell'overhead per la traduzione della query, ma i benefici che ottengo dalla compilazione sono ben superiori, il tutto trasparente ai vari strati. Sto preparando una libreria che contenga queste estensioni, supporti Code first e permette di pluggare manipulatore ed esecutori della query; presto la metterò online.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Architettura/" rel="tag"&gt;Architettura&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Entity_Framework/" rel="tag"&gt;Entity Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ/" rel="tag"&gt;LINQ&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2705/Prestazioni-Query-LINQ-Architetture-Complesse.aspx"&gt;&lt;em&gt;Prestazioni delle query LINQ in architetture complesse&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4.0, Architettura, Entity Framework, LINQ</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2705/Prestazioni-Query-LINQ-Architetture-Complesse.aspx</guid><slash:comments>1</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2705/Prestazioni-Query-LINQ-Architetture-Complesse.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2705.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2705</trackback:ping></item><item><title>Real Code Day 6: Windows Azure e MVVM su Windows Phone 7</title><link>http://blogs.aspitalia.com/ricciolo/post2704/Real-Code-Day-6-Windows-Azure-MVVM-Windows-Phone7.aspx</link><pubDate>Wed, 25 May 2011 14:18:57 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2704" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;La sesta edizione del nostro evento che si concentra sul codice è da poco passato e vorrei riassumere la giornata per quanto riguarda le mie sessioni.&lt;/p&gt; &lt;p&gt;Innanzitutto credo che il bilancio sia decisamente positivo; come già detto e dalle testimonianze dei partecipanti, la location era davvero ottima, confortevole e la fase di registrazione è andata per il meglio.&lt;/p&gt; &lt;p&gt;Nel corso della giornata ho tenuto più sessioni alcune delle quali con altri del gruppo. Prima di tutto con &lt;a href="http://blogs.aspitalia.com/daniele/"&gt;Daniele&lt;/a&gt; abbiamo visto le novità più importanti di &lt;strong&gt;HTML5&lt;/strong&gt; senza esagerare e restando sulle specifiche che sono mature. In particolare ho mostrato con Daniele il tag video facendo vedere pregi e difetti, dando un occhio ai player già preconfezionati per HTML5 sviluppati in HTML, JavaScript e CSS: in ModelVC abbiamo utilizzato &lt;a href="http://mediaelementjs.com/"&gt;MediaElement.js&lt;/a&gt;&lt;/p&gt; &lt;p&gt;E' stata poi la volta delle sessioni rapide. In 20 minuti ho presentato &lt;strong&gt;Windows Azure&lt;/strong&gt;, i servizi che fornisce e come con pochi click è possibile prendere un'applicazione web preesistente e portarla su Azure. Questa piattaforma forza il modo di pensare le applicazioni, in modo che siano scalabili il più possibile, e il messaggio che cerco sempre di trasmettere è quello di almeno informarsi su questa piattaforma e prenderla in considerazione per i nuovi sviluppi o per eventuali migrazioni, invece di scartarla con scetticismo, poiché può riservare sorprese, anche dal punto di vista economico.&lt;/p&gt; &lt;p&gt;Con tutta la ciurma di &lt;a href="http://www.5dlabs.it/"&gt;5DLabs&lt;/a&gt;, poi, ho tenuto una sessione su Windows Phone 7. La prima parte l'ho dedicata a presentare il &lt;strong&gt;pattern MVVM&lt;/strong&gt; e come realmente nel nostro gruppo lo utilizziamo per lavorare insieme ed essere produttivi. Di tutto questo potete trovare il materiale a &lt;a href="http://aspitalia.com/rcd-6"&gt;questo indirizzo&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;In conclusione sono molto soddisfatto della giornata, ho incontrato molta gente interessata alle tematiche e un doveroso grazie ai miei compagni di avventura con cui è sempre un piacere trascorrere il tempo libero e lavorativo.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Architettura/" rel="tag"&gt;Architettura&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/HTML5/" rel="tag"&gt;HTML5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Azure/" rel="tag"&gt;Windows Azure&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone/" rel="tag"&gt;Windows Phone&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone_7/" rel="tag"&gt;Windows Phone 7&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2704/Real-Code-Day-6-Windows-Azure-MVVM-Windows-Phone7.aspx"&gt;&lt;em&gt;Real Code Day 6: Windows Azure e MVVM su Windows Phone 7&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>OT, .NET Framework, .NET Framework 4.0, Architettura, HTML5, Windows Azure, Windows Phone, Windows Phone 7</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2704/Real-Code-Day-6-Windows-Azure-MVVM-Windows-Phone7.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2704/Real-Code-Day-6-Windows-Azure-MVVM-Windows-Phone7.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2704.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2704</trackback:ping></item><item><title>LINQ, lazy loading e architettura</title><link>http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx</link><pubDate>Fri, 11 Mar 2011 17:42:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2690" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Con l'avvento di LINQ l'accesso ai dati è decisamente cambiato. Con un timido &lt;b&gt;LINQ to SQL&lt;/b&gt; e un po' più maturo &lt;b&gt;LINQ to Entities&lt;/b&gt; abbiamo potuto interrogare le informazioni sfruttando ORM, oggetti, tipizzazione, compilazione delle query e tutti i benefici che ormai sappiamo.&lt;/p&gt;&lt;p&gt;Anche LINQ con il tempo ha dovuto trovare il suo posto e adattare/adattarsi hai layer e ai pattern che usiamo da tempo e, a mio avviso, si è trovato un ottimo compromesso che permetta di conciliare astrazione e la facilità di LINQ. Mi riferisco alla tipica separazione in layer che solitamente si fa tra repository, servizi di dominio e servizi applicativi che ha trovato alleato l'utilizzo dell'interfaccia &lt;b&gt;IQueryable&lt;/b&gt; per essere restituito dal repository e permette ai vari strati di aggiungere pezzi alla query per poter essere poi eseguita quando effettivamente la consumiamo.&lt;/p&gt;&lt;p&gt;Il nostro &lt;a href="http://blogs.aspitalia.com/cradle/"&gt;MarcoDes&lt;/a&gt; ha inserito questa tecnica in &lt;a href="http://modelvirtualcasting.codeplex.com/"&gt;Model Virtual Casting&lt;/a&gt;, e si dimostra molto comoda ed efficace se utilizzata con LINQ to Entities. Non voglio però parlare di questo dal punto di vista architetturale ma affrontare un problema tecnologico che ho dovuto affrontare. Quando infatti utilizziamo IQueryable ci ritroviamo con la problematica principale di dover indicare quali navigation property caricare all'interno delle entità che si stanno materializzando e, scartando l'ipotesi del &lt;b&gt;lazy loading&lt;/b&gt; per motivi di controllo ed efficienza&amp;#xa0;sulle query, si procede con l'indicare sul repository le proprietà da includere. Anche questo è implementato&amp;#xa0;in Model Virtual Casting e l'abbiamo rappresentato con un'interfaccia simile a questa.&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;interface&lt;/span&gt; IReadOnlyRepository&amp;lt;T&amp;gt;
{
  IQueryable&amp;lt;T&amp;gt; GetAll();
  IReadOnlyRepository&amp;lt;T&amp;gt; Include(&lt;span style="color:#0000FF"&gt;string&lt;/span&gt; path);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Esiste una variante che al posto della stringa richiede un &lt;b&gt;Expression&lt;/b&gt; per rendere tutto tipizzato, ma in sostanza il discorso non cambia. Quando da un servizio utilizziamo il repository di fatto faremo:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;IQueryable&amp;lt;Product&amp;gt; list = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ProductRepository().Include(&amp;quot;&lt;span style="color:#8B0000"&gt;Orders&lt;/span&gt;&amp;quot;).GetAll();&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In questo modo, quando sfogliamo list otteniamo popolata la classe Product con i rispettivi ordini attraverso la collezione esposta dalla proprietà Orders. Poiché l'implementazione del repository è basta su EF 40, la chiamata ad Include si traduce semplicemente alla chiamata alla funzione omonima di ObjectQuery&amp;lt;T&amp;gt; di LINQ to Entities.&lt;/p&gt;
&lt;p&gt;Il problema di questo è approccio è che qualora decidiamo di restituire la variabile list, facendola passare ad esempio dallo strato dei servizi a quello applicativo per effettuare un binding, perdiamo il riferimento al repository e di conseguenza la possibilità di aggiungere &lt;b&gt;Include&lt;/b&gt; anche su strati successivi. Se gli strati che si passano IQueryable e alterano la query non fanno altro che agire solo sull'expression tree, non è più probabile che sia l'utilizzatore finale a sapere quali proprietà si debba materializzare? A mio modo di vedere la risposta è sì e lo dimostra anche il fatto che spesso si utilizzano proezioni per ottenere un sottoinsieme dei membri disponibili su una classe.&lt;/p&gt;
&lt;p&gt;Per permettere quindi di effettuare gli Include su tutti gli strati ho pensato dapprima a la creazione di un'inferfaccia IMultiQueryable&amp;lt;T&amp;lt; che ereditando da IQueryable permetta sia di effettuare query ma anche di effettuare Include. Questa soluzione l'ho adottata con un cliente e si è dimostrata sempre funzionante portando solo con se la scomodità di fare il cast in certe situazioni su IMultiQueryable. Ho dunque pensato ad una soluzione alternativa che praticamente consiste nel creare un extension method personalizzato per rappresentare l'include:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;static&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; Include&amp;lt;T&amp;gt;(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt; IQueryable&amp;lt;T&amp;gt; source, &lt;span style="color:#0000FF"&gt;params&lt;/span&gt; Expression&amp;lt;Func&amp;lt;T, Object&amp;gt;&amp;gt;[] properties)
{
  MethodInfo method = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Type[] { &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(T) });
  var arguments = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Expression[] {
    source.Expression,
    Expression.NewArrayInit(&lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(Expression&amp;lt;Func&amp;lt;T, Object&amp;gt;&amp;gt;), properties.Select(p =&amp;gt; Expression.Quote(p))),
  };

  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; source.Provider.CreateQuery&amp;lt;T&amp;gt;(Expression.Call(&lt;span style="color:#0000FF"&gt;null&lt;/span&gt;, method, arguments));
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In modo simile a Where, OrderBy ecc, non faccio altro che creare un'espressione che chiama il metodo stesso Include. Questo mi permette di eliminare tale metodo dall'interfaccia di repository e di scrivere, ovunque sono, il seguente codice:
&lt;div class="codebox"&gt;&lt;pre&gt;IQueryable&amp;lt;Product&amp;gt; list = GetProductsFromRespository();
list = list.Include(p =&amp;gt; p.Orders).Take(10).Include(p =&amp;gt; p.Details);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Possiamo quindi combinare Include come qualsiasi altro extension method, su qualsiasi layer, basta che sia un IQueryable. E' chiaro però che così facendo quando LINQ to Entities dovrà convertire l'expression tree in SQL, non conoscerà il nostro metodo personalizzato e lancerà un'eccezione. Aggirare il problema però è più semplice di quanto si pensi, perché basta fornire un intermediario all'oggetto iniziale della query.&lt;/p&gt;
&lt;p&gt;Mettendoci a livello del repository possiamo infatti non restituire direttamente l'ObjectQuery restituito dall'ObjectContext di EF, ma restituire un wrapper da noi creato che implementa IQueryable.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; IQueryable&amp;lt;Product&amp;gt; GetAll()
{
  NorthwindContext c = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; NorthwindContext();
  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; ObjectMultiQuery&amp;lt;T&amp;gt;(c.Products);
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Implementare IQueryable se si deve fare solo da intermediari è piuttosto semplice, perché la nostra unica intenzione è porci in mezzo prima di eseguire la query su database. Per farlo dobbiamo implementare &lt;b&gt;IEnumerable.GetEnumerator&lt;/b&gt; e &lt;b&gt;IQueryProvider.Execute&lt;/b&gt;, alterare l'espression tree creato e passarlo al motore di LINQ to Entities per eseguirla.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; IEnumerator&amp;lt;T&amp;gt; GetEnumerator()
{
  &lt;span style="color:#008000"&gt;// Trasformo l&amp;#39;espressione per LINQ to Entities&lt;/span&gt;
  IncludeVisitor compiler = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; IncludeVisitor();
  Expression newExpression = compiler.Visit(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.Expression);

  &lt;span style="color:#008000"&gt;// Creo la nuova query utilizzando ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
  IEnumerable&amp;lt;T&amp;gt; result = &lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.original.Provider.CreateQuery&amp;lt;T&amp;gt;(newExpression) &lt;span style="color:#0000FF"&gt;as&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt;;

  &lt;span style="color:#008000"&gt;// Ottengo il risultato&lt;/span&gt;
  &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; result.GetEnumerator();
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il campo original è l'oggetto originale EF ottenuto con c.Products nel codice precedente e rappresenta l'engine di EF. La classe IncludeVisitor invece ha il compito di trasformare l'espressione, cioè tradurre le chiamate all'extension method Include, al metodo ObjectQuery.Include. Ci viene in aiuto la classe &lt;b&gt;ExpressionVisitor&lt;/b&gt; dalla quale possiamo ereditare e sovrascrivere il metodo VisitMethodCall per cambiare l'espressione di chiamata. Riporto il codice con i commenti così da capire meglio come funziona:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;class&lt;/span&gt; IncludeVisitor : ExpressionVisitor
{
  &lt;span style="color:#0000FF"&gt;protected&lt;/span&gt; &lt;span style="color:#0000FF"&gt;override&lt;/span&gt; Expression VisitMethodCall(MethodCallExpression node)
  {
    &lt;span style="color:#0000FF"&gt;if&lt;/span&gt; (node.Method.DeclaringType == &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(Extensions) &amp;amp;&amp;amp; node.Method.Name == &amp;quot;&lt;span style="color:#8B0000"&gt;Include&lt;/span&gt;&amp;quot;)
    {
      PropertiesVisitor visitor = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; PropertiesVisitor();

      &lt;span style="color:#008000"&gt;// ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      Type objectQueryType = &lt;span style="color:#0000FF"&gt;typeof&lt;/span&gt;(ObjectQuery&amp;lt;&amp;gt;).MakeGenericType(node.Arguments[0].Type.GetGenericArguments());
      &lt;span style="color:#008000"&gt;// Visito il context cos&amp;#236; conto anch&amp;#39;esso come parametro&lt;/span&gt;
      &lt;span style="color:#008000"&gt;// Effettuo un convert per essere sicuro che sia un ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      Expression exp = Expression.Convert(&lt;span style="color:#0000FF"&gt;this&lt;/span&gt;.Visit(node.Arguments[0]), objectQueryType);

      &lt;span style="color:#008000"&gt;// Trovo il metodo include specifico di ObjectQuery&amp;lt;T&amp;gt;&lt;/span&gt;
      MethodInfo includeMethod = objectQueryType.GetMethod(&amp;quot;&lt;span style="color:#8B0000"&gt;Include&lt;/span&gt;&amp;quot;, BindingFlags.Public | BindingFlags.Instance);

      &lt;span style="color:#008000"&gt;// Chiama il metodo Include per tutte le espressioni passate&lt;/span&gt;
      &lt;span style="color:#0000FF"&gt;foreach&lt;/span&gt; (var property &lt;span style="color:#0000FF"&gt;in&lt;/span&gt; ((NewArrayExpression)node.Arguments[1]).Expressions)
      {
        visitor.FindProperties(property);

        &lt;span style="color:#008000"&gt;// Concateno le propriet&amp;#224; trovate con il punto&lt;/span&gt;
        exp = Expression.Call(exp, includeMethod, Expression.Constant(String.Join(&amp;quot;&lt;span style="color:#8B0000"&gt;.&lt;/span&gt;&amp;quot;, visitor.PropertyNames)));
      }

      &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; exp;
    }
    &lt;span style="color:#0000FF"&gt;return&lt;/span&gt; &lt;span style="color:#0000FF"&gt;base&lt;/span&gt;.VisitMethodCall(node);
  }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In questo modo l'expression tree originale cambia così:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#008000"&gt;// Da&lt;/span&gt;
Convert(&lt;span style="color:#0000FF"&gt;value&lt;/span&gt;(System.Data.Objects.ObjectSet`1[Product])).MergeAs(AppendOnly).Include(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; [] {c =&amp;gt; c.Orders}).Take(10)
&lt;span style="color:#008000"&gt;// A&lt;/span&gt;
Convert(Convert(&lt;span style="color:#0000FF"&gt;value&lt;/span&gt;(System.Data.Objects.ObjectSet`1[Product])).MergeAs(AppendOnly)).Include(&amp;quot;&lt;span style="color:#8B0000"&gt;Orders&lt;/span&gt;&amp;quot;).Take(10)&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Trovo questa soluzione veloce ed efficace ed è soprattutto approvata da &lt;a href="http://blogs.aspitalia.com/cradle/"&gt;MarcoDes&lt;/a&gt; :-D. Trovate l'esempio nelle &lt;a href="http://lab.aspitalia.com/Ricciolo/Downloads/Codemotion11.zip"&gt;demo&lt;/a&gt; di Codemotion 2011 svoltosi a Roma pochi giorni fa. Enjoy!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Architettura/" rel="tag"&gt;Architettura&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Entity_Framework/" rel="tag"&gt;Entity Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ/" rel="tag"&gt;LINQ&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/LINQ_to_Entities/" rel="tag"&gt;LINQ to Entities&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx"&gt;&lt;em&gt;LINQ, lazy loading e architettura&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 3.5, .NET Framework 4.0, Architettura, Entity Framework, LINQ, LINQ to Entities</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx</guid><slash:comments>1</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2690/LINQ-Lazy-Loading-Architettura.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2690.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2690</trackback:ping></item><item><title>Push notification per Windows Phone con il .NET Framework</title><link>http://blogs.aspitalia.com/ricciolo/post2677/Push-Notification-Windows-Phone-.NET-Framework.aspx</link><pubDate>Sun, 02 Jan 2011 19:18:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2677" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;

Scrivo questo post per segnalare un piccolo problema in cui ci si può imbattere se si vuole mandare notifiche ad un device. Su MSDN o per la rete si trovano piccoli esempio che preparano l'XML per toast o tile concatenando il testo. Siamo nel 2011 e direi che è ora di scrivere il codice bene utilizzando uno dei molteplici modi che il .NET Framework mette a disposizione, come&lt;strong&gt; LINQ to XML&lt;/strong&gt;, ed evitare problemi di caratteri speciali.&lt;/p&gt;&lt;p&gt;Nel mio codice ho dovuto quindi, una volta preparato l'XML, salvarlo in uno &lt;strong&gt;Stream&lt;/strong&gt; per poi tenermi i byte da inviare con &lt;strong&gt;WebClient&lt;/strong&gt; o &lt;strong&gt;WebRequest&lt;/strong&gt;, con qualcosa simile a questo:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;using&lt;/span&gt; (MemoryStream stream = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; MemoryStream())
{
  &lt;span style="color:#0000FF"&gt;using&lt;/span&gt; (XmlWriter writer = XmlWriter.Create(stream, settings))
  {
    doc.Save(writer);
    writer.Flush();

    data = stream.ToArray();
  }
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inviando poi la variabile &lt;em&gt;data&lt;/em&gt; con un &lt;em&gt;POST&lt;/em&gt; le notifiche però non arrivavano. Debuggando una toast notification mentre l'app&amp;#xa0;era attiva, ricevevo una eccezione che però non potevo intercettare, perché generata da codice della libreria Microsoft. Dopo vari tantitivi ho capito che il problema stava nel &lt;strong&gt;preamble&lt;/strong&gt; dell'encoding: tre byte inseriti all'inizio dello &lt;em&gt;Stream&lt;/em&gt; per indicare il tipo di codifica utilizzata per il testo XML. Sebbene non dovrebbe essere un problema a &lt;strong&gt;Windows Phone&lt;/strong&gt;, a lui non piace e&amp;#xa0;dato che usavo un &lt;strong&gt;UTF8&lt;/strong&gt; e l'encoding viene letto dall'header HTTP, ho dovuto rimuovere questa informazione creando l'encoding a mano e passando il parametro di preamble a false.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;byte&lt;/span&gt;[] data;
Encoding encoding = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; UTF8Encoding(&lt;span style="color:#0000FF"&gt;false&lt;/span&gt;);

XmlWriterSettings settings = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; XmlWriterSettings();
settings.Encoding = encoding;

&lt;span style="color:#0000FF"&gt;using&lt;/span&gt; (MemoryStream stream = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; MemoryStream())
{
  &lt;span style="color:#0000FF"&gt;using&lt;/span&gt; (XmlWriter writer = XmlWriter.Create(stream, settings))
  {
    doc.Save(writer);
    writer.Flush();

    data = stream.ToArray();
  }
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Spero vi sia utile.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone/" rel="tag"&gt;Windows Phone&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone_7/" rel="tag"&gt;Windows Phone 7&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XML/" rel="tag"&gt;XML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2677/Push-Notification-Windows-Phone-.NET-Framework.aspx"&gt;&lt;em&gt;Push notification per Windows Phone con il .NET Framework&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Windows Phone, .NET Framework, .NET Framework 4.0, Windows Phone 7, XML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2677/Push-Notification-Windows-Phone-.NET-Framework.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2677/Push-Notification-Windows-Phone-.NET-Framework.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2677.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2677</trackback:ping></item><item><title>Take Me Back e l&amp;#39;architettura</title><link>http://blogs.aspitalia.com/ricciolo/post2676/Take-Back-Architettura.aspx</link><pubDate>Wed, 22 Dec 2010 21:15:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2676" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;I miei compagni di avventura &lt;a href="http://blogs.aspitalia.com/novecento/"&gt;Alessio&lt;/a&gt; e &lt;a href="http://blogs.aspitalia.com/nostromo/"&gt;Marco&lt;/a&gt; vi hanno già introdotto a &lt;a href="http://redirect.zune.net/redirect/preferences/askclient?ReturnUrl=http%3a%2f%2fsocial.zune.net%2fredirect%3ftype%3dphoneApp%26id%3d9d0650dd-a3d6-df11-a844-00237de2db9e%26source%3dAppsFuze"&gt;Take Me Back&lt;/a&gt;: la nostra prima applicazione &lt;a href="http://www.ozosoftware.com/"&gt;OzoSoftware&lt;/a&gt;. Con questo e altri post vorrei parlarvi delle tecniche impiegate per la realizzazione dell'applicazione di cui, per metodologia di sviluppo, impegno e risultato vado molto fiero.&lt;/p&gt;&lt;p&gt;Partiamo dall'architettura che sfrutta un framework appositamente sviluppato per facilitarci appositamente nello sviluppo di applicazioni per&lt;strong&gt; Windows Phone 7&lt;/strong&gt;, usato poi nell'applicazione per &lt;a href="zune://navigate/?appID=67d9c455-25d6-df11-a844-00237de2db9e"&gt;ASPItalia.com&lt;/a&gt;. Senza grosse pretese, non abbiamo abbondato di astrazione, ma ci siamo limitati (per ora) alle tecniche più classiche di architettura&amp;#xa0;che si usano con&amp;#xa0;Silverlight, adattandole leggermente. Prima di tutto è basato su &lt;strong&gt;MVVM&lt;/strong&gt;, sviluppando classi base, mediator pattern e classi più core (che colmano la mancanza di certe API perché basato su SL 3.0) create da un fork del &lt;a href="http://www.galasoft.ch/mvvm/getstarted/"&gt;MVVM Light Toolkit&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Ci siamo concentrati nello sviluppare i view model in modo che siano completamente testabili, perciò tutti gli aspetti che riguardano MessageBox, gestione errori, canale notifiche, task e chooser, sono affidati dal mediator pattern, di cui parlo in &lt;a href="http://www.google.com/url?sa=t&amp;source=web&amp;cd=1&amp;ved=0CBYQFjAA&amp;url=http%3A%2F%2Fwww.winfxitalia.com%2Farticoli%2Fpresentation-foundation%2Farchitettura-model-view-viewmodel-wpf-problemi-comuni-p-3.aspx&amp;ei=yGMSTaqENsWn4Abjz7mGAg&amp;usg=AFQjCNGx373hr2oNbuTh95GwlsXcuNxE9g"&gt;questo&lt;/a&gt; articolo: lancio il messaggio e qualcuno, la parte legata alla view, agisce di conseguenza.&lt;/p&gt;&lt;p&gt;La variazione sul tema MVVM risiede nell'associazione &lt;strong&gt;View-ViewModel&lt;/strong&gt;. Poiché è nel ViewModel che eseguo i comandi e spesso l'attività è quella di navigare tra le pagine, abbiamo scelto di sviluppare un oggetto&amp;#xa0;&lt;strong&gt;ViewModelApplication&lt;/strong&gt; che tramite il metodo &lt;strong&gt;NavigateToViewModel&lt;/strong&gt; permette di navigare ad un'altra pagina. In un'applicazione Windows Phone di fatto ogni pagina (la view) ha il suo ViewModel e solitamente la navigazione è richiesta da esso. Richiedendo la navigazione per ViewModel, posso istanziarlo come voglio (al volo,&amp;#xa0;IoC, ecc) e passare parametri che possono servire al ViewModel da mostrare. Di fatto il &lt;em&gt;ViewModelApplication&lt;/em&gt; è un controller pluggabile per la navigazione tra pagine. Il bello è affidato al &lt;strong&gt;IViewBinder&lt;/strong&gt;, la cui implementazione predefinita risolve la View a cui navigare via reflection. Se richiediamo di navigare quindi ad un'istanza o al tipo &lt;em&gt;MapViewModel&lt;/em&gt;, il frame navigherà all'uri &lt;em&gt;MapView.xaml.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;ViewModelApplication.NavigateToViewModel(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; MapViewModel());&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;Il controller che gestisce quindi la navigazione tra le pagine ci permette di avere un po' di funzionalità in più che fanno molto comode. Prima tra tutte la possibilità di implementare l'interfaccia &lt;strong&gt;IViewModelNavigation&lt;/strong&gt; sul VM per gestire gli eventi di navigazione &lt;em&gt;NavigatingFrom&lt;/em&gt;, &lt;em&gt;NavigatedFrom&lt;/em&gt;, &lt;em&gt;NavigatedTo&lt;/em&gt;, comodo per avviare il caricamento delle informazioni o fermarle quando si esce dalla pagina. Poi la possibilità di implementare l'interfaccia &lt;strong&gt;IPersistable&lt;/strong&gt;, per salvare o caricare le informazioni per il tombstoning. E' tutto automatizzato, se la pagina si chiude viene chiamato il &lt;em&gt;SaveState&lt;/em&gt;, se si riapre il &lt;em&gt;LoadState&lt;/em&gt;; se il ViewModel infatti rappresenta le informazioni da mostrare tramite la View, è in esso che vanno persistite o mostrate.&lt;/p&gt;&lt;p&gt;Poiché alcune informazioni sono condivise tra più ViewModel è difficile determinare chi ha il compito di salvarle nella fase di tombstoning, per cui abbiamo optato per creare della classi singleton che si autogestiscono. Implementando la classe &lt;strong&gt;IKeyPersistable&lt;/strong&gt; si registrano al motore con &lt;strong&gt;ViewModelApplication.RegisterPersistable&lt;/strong&gt; per partecipare anch'esse alla fase di tombstoning. Tutto questo ha semplificato notevolmente la gestione del tombstoning, perché affidata ad ogni parte a cui compete. Non serve neanche un locator dei ViewModel perché questi sono sempre indipendenti tra loro o eventualmente lavorano con intermediari sopra citati.&lt;/p&gt;&lt;p&gt;Per quanto riguarda infine il supporto a &lt;strong&gt;Blend&lt;/strong&gt;, ci limitiamo ad usare il &lt;strong&gt;DataContext&lt;/strong&gt; del namespace di design di blend, utilizzando la voce &lt;em&gt;&amp;quot;Create Sample Data From Class&amp;quot;&lt;/em&gt; che ci assicura di avere il supporto a design time allineato al ViewModel sottostante.&lt;/p&gt;&lt;p&gt;Nel prossimo post vi parlerò di come abbiamo gestito la parte delle chiamate HTTP che ha richiesto molto lavoro per creare una soluzione completa.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/Architettura/" rel="tag"&gt;Architettura&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone/" rel="tag"&gt;Windows Phone&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Phone_7/" rel="tag"&gt;Windows Phone 7&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Presentation_Foundation/" rel="tag"&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2676/Take-Back-Architettura.aspx"&gt;&lt;em&gt;Take Me Back e l&amp;#39;architettura&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Windows Phone, Architettura, Windows Phone 7, Windows Presentation Foundation, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2676/Take-Back-Architettura.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2676/Take-Back-Architettura.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2676.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2676</trackback:ping></item><item><title>Progress di una chiamata Silverlight ad un servizio</title><link>http://blogs.aspitalia.com/ricciolo/post2639/Progress-Chiamata-Silverlight-Servizio.aspx</link><pubDate>Wed, 09 Jun 2010 16:13:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2639" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Ormai si sa, Silverlight come unico strumento di accesso ad informazioni remote, permette di usare i servizi, siano essi sviluppati lato server in asmx, &lt;b&gt;WCF&lt;/b&gt; o altre tecnologie. Non è propriamente l'unica perché possiamo effettuare chiamate HTTP generiche e tramite REST/POX ottenere sottoforma di Json e XML i dati. Ad ogni modo i servizi usano uno standard e sono molto comodi e facili da utilizzare, grazie alla generazione automatica del proxy.&lt;/p&gt;&lt;p&gt;Durante un corso mi è stato però chiesto se possiamo conoscere lo stato di avanzamento di una chiamata ad un servizio. Partiamo dal presupposto che un servizio non dovrebbe mai restituire una quantità notevole di dati per due principali motivi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;è una chiamata HTTP, se qualcosa si interrompe siamo costretti a rieffettuare la chiamata e riottenere l'intera risposta;&lt;/li&gt;&lt;li&gt;è probabile che tutti questi dati non servano per intero all'utente fin dall'inizio e una buona politica di frammentazione di download delle informazioni è la strada ideale.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Ad ogni modo, un servizio che restituisce 1/5MB può essere accettabile e l'ideale sarebbe fornire lo stato di avanzamento all'utente. Per capire come conoscere lo stato di avanzamento dobbiamo prima di tutto sapere che sia Silverlight, lato client, che WCF, lato server, bufferizzano la richiesta e la risposta. Questo significa che entrambi preparano il messaggio &lt;b&gt;SOAP&lt;/b&gt;, lo serializzano e lo mandano in risposta, o viceversa, leggono i byte della richiesta/risposta e solo quando interamente caricata preparano il messaggio e lo interpretano.&lt;/p&gt;&lt;p&gt;Poiché a noi interessa l'aspetto Silverlight dobbiamo prima di tutto modificare nel file &lt;b&gt;ServiceReferences.ClientConfig&lt;/b&gt; l'attributo transferMode:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;basichttpbinding&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;binding&lt;/span&gt; &lt;span style="color:#FF0000"&gt;transfermode&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;StreamedResponse&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000FF"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000"&gt;binding&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;/basichttpbinding&gt;&lt;p&gt;In questo modo il binding HTTP di Silverlight comincerà a leggere la risposta pian piano che i byte giungono dal server. Questo però non basta perché non abbiamo cognizione dell'avanzamento della lettura della risposta. In Silverlight 4.0 possiamo scrivere behavior, binding e inserire message inspector, tutte cose ereditate da WCF del .NET Framework, ma non possiamo riscrivere parzialmente il &lt;b&gt;basicHttpBinding&lt;/b&gt; e in generale &lt;b&gt;HttpChannelFactory&lt;/b&gt;. Fortunatamente questo oggetto sfrutta al suo interno, per effettuare fisicamente la chiamata HTTP, la classe &lt;b&gt;HttpWebRequest&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Per conoscere lo stato di avanzamento possiamo quindi personalizzare il modo in cui l'HttpWebRequest viene creato. Per farlo nel .NET Framework, ma anche in Silverlight, abbiamo a disposizione il metodo statico &lt;b&gt;WebRequest.RegisterPrefix&lt;/b&gt; per indicare, in base allo schema, quale &lt;b&gt;IWebRequestCreate&lt;/b&gt; utilizzare. Normalmente possiamo scegliere tra &lt;b&gt;WebRequestCreator.BrowserHttp&lt;/b&gt; e &lt;b&gt;WebRequestCreator.ClientHttp&lt;/b&gt;. Il primo sfrutta lo stesso motore del browser e contiene quindi i cookie del dominio e permette al browser di leggere la risposta, mentre il secondo scavalca il browser e permette di effettuare chiamate HTTP in liberà.&lt;/p&gt;&lt;p&gt;L'idea è quindi di creare un IWebRequestCreate e relativi HttpWebRequest, HttpWebResponse e Stream personalizzati che mi permettano di sapere a che punto si trova la lettura dello Stream. Quando infatti impostiamo il transferMode a streamed viene impostato sull'oggetto HttpWebRequest la proprietà &lt;b&gt;AllowReadStreamBuffering&lt;/b&gt; a false, permettendo la lettura dello Stream mentre riceviamo i byte.&lt;/p&gt;&lt;p&gt;Per andare al sodo, &lt;a href="http://www.cristiancivera.com/Downloads/wcfprogress.zip"&gt;qua &lt;/a&gt;trovate un'applicazione di esempio. Prima di tutto registro il mio creator personalizzato:&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;WebRequest.RegisterPrefix(&amp;quot;&lt;span style="color:#8B0000"&gt;http://&lt;/span&gt;&amp;quot;, AdvancedWebRequestCreator.Default);&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Tramite esso posso poi intercettare l'evento che mi notifica lo stato di avanzamento di una chiamata.&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;AdvancedWebRequestCreator.Default.UriProgressChanged += &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; EventHandler&amp;lt;UriProgressChangedEventArgs&amp;gt;(Default_UriProgressChanged);&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;Nell'evento so l'URI del servizio che sto chiamando, la percentuale, i byte scaricati e totali. Ho anche aggiunto una proprietà per indicare, per ogni URI, quale creator utilizzare, utile per quando usiamo i due client (http e browser) in modo misto.&lt;/p&gt;&lt;div class="codebox"&gt;&lt;pre&gt;AdvancedWebRequestCreator.Default.Mappings.Add(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; UriCreateMapping(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Uri(&amp;quot;&lt;span style="color:#8B0000"&gt;http://sito.it&lt;/span&gt;&amp;quot;), WebRequestCreator.ClientHttp));&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Per il resto basta chiamare il servizio come normalmente facciamo. Un'ultima nota per quanto riguarda WCF lato server: il transferMode dev'essere obbligatoriamente su buffered altrimenti la risposta non conterrà il &lt;b&gt;ContentLength&lt;/b&gt; ed è impossibile per noi indicare lo stato.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Web_Service/" rel="tag"&gt;Web Service&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Communication_Foundation/" rel="tag"&gt;Windows Communication Foundation&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2639/Progress-Chiamata-Silverlight-Servizio.aspx"&gt;&lt;em&gt;Progress di una chiamata Silverlight ad un servizio&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Silverlight, .NET Framework 3.0, Web Service, Windows Communication Foundation, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2639/Progress-Chiamata-Silverlight-Servizio.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2639/Progress-Chiamata-Silverlight-Servizio.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2639.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2639</trackback:ping></item><item><title>Inside ModelVirtualCasting #5: i servizi</title><link>http://blogs.aspitalia.com/ricciolo/post2636/Inside-ModelVirtualCasting-Sharp5-Servizi.aspx</link><pubDate>Mon, 07 Jun 2010 15:58:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2636" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Quarto post della serie sugli internals dell'applicazione che abbiamo
 mostrato nel corso della Real Code Conference 4.0 lo scorso 25 Maggio 
2010 i cui sorgenti sono disponibili &lt;a href="http://modelvirtualcasting.codeplex.com/"&gt;su Codeplex&lt;/a&gt;:&lt;/p&gt; &lt;ol&gt;&lt;li&gt;&lt;a href="http://blogs.aspitalia.com/cradle/post2627/Inside-ModelVirtualCasting-Sharp1-Introduzione-Repository.aspx"&gt;Introduzione
 ai repository&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.aspitalia.com/cradle/post2629/Inside-ModelVirtualCasting-Sharp2-Architettura-Interna-Repository.aspx"&gt;Architettura
 interna dei repository&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.aspitalia.com/daniele/post2630/Inside-ModelVirtualCasting-Sharp3-Cache.aspx"&gt;La
 cache&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.aspitalia.com/cradle/post2634/Inside-ModelVirtualCasting-Sharp4-Funziona-CacheThis.aspx"&gt;Come funziona CacheThis&lt;/a&gt;&lt;/li&gt;&lt;li&gt;I servizi&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I servizi sono uno strato presente sin dalla prima versione di MVC e svolgono un ruolo cruciale nel nostro progetto: rappresentano il punto di accesso alle informazioni e sono l'intermediario verso il repository. Durante il RCC ho voluto quindi mostrare come, una volta preparato l'accesso al database tramite Entity Framework e modellato l'object model, sia semplice con &lt;strong&gt;Windows Communication Foundation&lt;/strong&gt; esporre in molteplici modi le informazioni verso il web o verso applicativi di nostra realizzazione.&lt;/p&gt;&lt;p&gt;Il nostro progetto prevede infatti:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;un'applicazione Silverlight per la consultazione delle modelle;&lt;/li&gt;&lt;li&gt;un'applicazione WPF per la gestione delle modelle e nello specifico delle foto/video;&lt;/li&gt;&lt;li&gt;alcune pagine AJAX per la consultazione delle modelle tramite REST;&lt;/li&gt;&lt;li&gt;l'esposizione delle informazioni anche mediante Open Data Protocol (OData);&lt;/li&gt;&lt;li&gt;la generazione di un feed RSS per le notizie.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Nei progetti &lt;em&gt;ASPItalia.ModelVirtualCasting.WCF.Services&lt;/em&gt; e &lt;em&gt;ASPItalia.ModelVirtualCasting.WCF.Contracts&lt;/em&gt; possiamo quindi trovare la definizione dei servizi e la loro implementazione. I contratti sono dei &lt;strong&gt;DTO&lt;/strong&gt;, cioè un sottoinsieme delle informazioni relative alle modelle e supportano il versioning. In questo modo durante le fasi di preparazione, abbiamo potuto lavorare in modo separato, senza dover aspettare che l'OO e il repository fossero pronti ed inoltre evitiamo di rompere la compatibilità con consumer che utilizzano contratti vecchi.&lt;/p&gt;&lt;p&gt;I servizi sono esposti con binding &lt;strong&gt;basicHttpBinding &lt;/strong&gt;(per SOAP, utilizzato dai due applicativi) e webHttpBinding (per le pagine AJAX). Il servizio è raggiungibile tramite il file &lt;em&gt;ModelsManager.svc&lt;/em&gt; o tramite gli alias /webAPI, /feed e /odata che ho definito nel &lt;em&gt;global.asax&lt;/em&gt;. Il servizio principale è addobbato di attribute per sfruttare REST o sfruttare anche le nuove caratteristiche di WCF 4.0. Nel web.config è infatti abilitato l'auto help page (raggiungibile all'indirizzo /webAPI/help).&lt;/p&gt;&lt;p&gt;L'uri odata espone un servizio WCF Data Service che si appoggia ad una sorgente personalizzata che, sempre tramite DTO, permette di accedere alle informazioni secondo lo standard. Di fatto ho messo in pratica lo script &lt;a href="http://www.winfxitalia.com/liste/usag/script.aspx?ID=173"&gt;#173&lt;/a&gt;. Sull'uri feed risponde invece il &lt;em&gt;SyndicationService&lt;/em&gt;, il quale restituire le news delle modelle.&lt;/p&gt;&lt;p&gt;Insomma, ho incluso WCF in tutte le salse (almeno quelle web) per dimostrare poi quanto in realtà è semplice. Seguirà un altro post per mostrare come con Javascript, le ASP.NET AJAX e/o jQuery possiamo interrogare questi servizi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Model_Virtual_Casting/" rel="tag"&gt;Model Virtual Casting&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/WCF_Data_Services/" rel="tag"&gt;WCF Data Services&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Communication_Foundation/" rel="tag"&gt;Windows Communication Foundation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2636/Inside-ModelVirtualCasting-Sharp5-Servizi.aspx"&gt;&lt;em&gt;Inside ModelVirtualCasting #5: i servizi&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4.0, Model Virtual Casting, WCF Data Services, Windows Communication Foundation</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2636/Inside-ModelVirtualCasting-Sharp5-Servizi.aspx</guid><slash:comments>1</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2636/Inside-ModelVirtualCasting-Sharp5-Servizi.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2636.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2636</trackback:ping></item><item><title>Quando usare gli optional parameter di C# 4</title><link>http://blogs.aspitalia.com/ricciolo/post2616/Usare-Optional-Parameter-CSharp.aspx</link><pubDate>Wed, 28 Apr 2010 18:14:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2616" border="0" style="width:1px; height:1px;" /&gt;
&lt;p&gt;Ormai si sa: tra le novità di &lt;strong&gt;C# 4&lt;/strong&gt; vi è la possibilità di usare parametri opzionali nei metodi. Non voglio parlare di come si dichiarano metodi e come si usano, perché già ne parla &lt;a href="http://blogs.aspitalia.com/az/"&gt;Andrea&lt;/a&gt; in &lt;a href="http://www.winfxitalia.com/articoli/netfx4/vb-2010-csharp-4.aspx"&gt;questo&lt;/a&gt; articolo. Voglio piuttosto soffermarmi sull'utilità e l'ambito di utilizzo.&lt;/p&gt; &lt;p&gt;Partiamo da un semplice esempio:&lt;/p&gt; &lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;void&lt;/span&gt; DoSomething(&lt;span style="color:#0000FF"&gt;string&lt;/span&gt; s = &amp;quot;&lt;span style="color:#8B0000"&gt;&lt;/span&gt;&amp;quot;)
{
  &lt;span style="color:#008000"&gt;// Faccio qualcosa&lt;/span&gt;
}&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Compilandolo possiamo dare un'occhiata all'assembly risultante e analizzare il metodo DoSomething, il cui IL in realtà è identico al passato. Nessuna nuova funzionalità dell'&lt;strong&gt;IL&lt;/strong&gt; quindi, ma solo due attributi applicati ad ogni parametro: &lt;strong&gt;Optional&lt;/strong&gt; e &lt;strong&gt;DefaultParameterValue&lt;/strong&gt;. Entrambi sono contenuti nel namespace System.Runtime.InteropServices e sono solamente informazioni utilizzate dal compilatore. Di fatto possiamo infatti dichiarare il metodo in questo modo:&lt;/p&gt; &lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;void&lt;/span&gt; DoSomething([Optional, DefaultParameterValue(&amp;quot;&lt;span style="color:#8B0000"&gt;&lt;/span&gt;&amp;quot;)] &lt;span style="color:#0000FF"&gt;string&lt;/span&gt; s)
{
}&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;La prima nota interessante riguarda Visual Basic. Fin dalla sua prima versione (per .NET) ha sempre supportato gli optional parameter e il compilatore produce tali attributi. Questo quindi conferma la convergenza dei due linguaggi ed è, una volta tanto, un punto a favore di Visual Basic.&lt;/p&gt; &lt;p&gt;Passiamo quindi all'utilizzo del metodo. Gli attributi vengono letti da Visual Studio e tramite l'intellisense ci viene mostrato il parametro opzionale e il suo valore predefinito. Chiamiamo il metodo senza indicare il parametro:&lt;/p&gt; &lt;div class="codebox"&gt;&lt;pre&gt;DoSomething();&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Compiliamo e guardando l'assembly possiamo notare che in realtà la chiamata a DoSomething è completa, con tanto di stringa vuota:&lt;/p&gt; &lt;div class="codebox"&gt;&lt;pre&gt;DoSomething(&amp;quot;&lt;span style="color:#8B0000"&gt;&lt;/span&gt;&amp;quot;);&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;Questo significa che contrariamente a quanto abbiamo è pensato quando abbiam visto gli optional parameter, non si sostituiscono agli overload dei metodi. Poniamo infatti di avere un assembly A con un metodo che dispone di parametri opzionali. L'assembly B lo referenzia e con la compilazione chiama il metodo con il valore X. In un successivo momento cambiamo l'assembly A e il valore opzionale in Y. L'assembly B continuerà ad usare il valore X. Questo &amp;quot;difetto&amp;quot; non c'è con gli overload dei metodi ed è il medesimo che hanno le costanti nei confronti dei membri statici.&lt;/p&gt; &lt;p&gt;Potremmo dire che &amp;quot;basta saperlo&amp;quot;, ma non è così semplice. Meglio evitare certi pericoli e difatti, da quanto mi risulta, gli optional parameter non sono &lt;strong&gt;CLS compliant&lt;/strong&gt;. Non a caso nel .NET Framework 4.0 gli optional paramenter non sono usati e gli overload persistono. Ma allora quando ha senso usarli? Per i membri privati, dove sappiamo che ricompilando i valori comunque cambiano, ma personalmente non mi piace: gli attributi messi per queste cose non mi piacciono.&lt;/p&gt; &lt;p&gt;Il vero motivo per cui esistono è per supportare &lt;strong&gt;COM&lt;/strong&gt;. Insieme a dynamic, gli optional parameter semplificano notevolmente l'interop con componenti farciti di parametri opzionali, primi tra tutti le PIA di Office. Prima di C# 4, chiamare COM era davvero un delirio.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2616/Usare-Optional-Parameter-CSharp.aspx"&gt;&lt;em&gt;Quando usare gli optional parameter di C# 4&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 4.0</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2616/Usare-Optional-Parameter-CSharp.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2616/Usare-Optional-Parameter-CSharp.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2616.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2616</trackback:ping></item><item><title>Routing alla massima potenza</title><link>http://blogs.aspitalia.com/ricciolo/post2605/Routing-Massima-Potenza.aspx</link><pubDate>Wed, 07 Apr 2010 06:24:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2605" border="0" style="width:1px; height:1px;" /&gt;
&lt;p&gt;Il routing è quella funzionalità introdotta con &lt;strong&gt;ASP.NET 3.5 SP1&lt;/strong&gt;, grazie ad una necessità di ASP.NET MVC, che ci permette creare URI decisamente più &lt;a href="http://www.google.it/url?sa=t&amp;source=web&amp;ct=res&amp;cd=1&amp;ved=0CBIQFjAA&amp;url=http%3A%2F%2Fit.wikipedia.org%2Fwiki%2FOttimizzazione_(motori_di_ricerca)&amp;ei=D_m1S-T2MMTs-AbRotXJAg&amp;usg=AFQjCNEEbG8va-5vzZuEWGmc4Cl_xeQuaw" target="_blank"&gt;SEO&lt;/a&gt;. Nel nostro libro su &lt;a href="http://books.aspitalia.com/ASP.NET-4.0/" target="_blank"&gt;ASP.NET 4.0&lt;/a&gt; ne parlo abbondantemente e la sua forza risiede nella sua indipendenza dall'handler che deve processare la richiesta. Non dobbiamo infatti pensare che sia una caratteristica limitata ad &lt;strong&gt;ASP.NET MVC&lt;/strong&gt; ne tanto meno ad&lt;strong&gt; ASP.NET WebForm&lt;/strong&gt;. A tal proposito è curioso come si tende a separare le due tecnologie quando una &lt;strong&gt;ViewPage&lt;/strong&gt; (classe base delle view di MVC) sia comunque una &lt;strong&gt;Page&lt;/strong&gt; (classe base delle webform) che da essa erediti tutte le caratteristiche in parte poi non utilizzate, ma che in ogni modo lo rende un handler ASP.NET sottoposto alla medesima pipeline di esecuzione di una richiesta.&lt;/p&gt; &lt;p&gt;Volendo allargare ancora di più la visione, ASP.NET si presta anche per altri motori, come per esempio i servizi WCF. Se ne sviluppiamo uno, possiamo ospitarlo all'interno di IIS tramite i file .svc, ma questo presenta, soprattutto per le WebAPI esposte tramite REST, un brutto difetto. Un &lt;strong&gt;WCF Data Services&lt;/strong&gt; viene infatti raggiungo con un URI simile a &lt;em&gt;http://localhost:41874/WcfDataService1.svc/MiaOperazione&lt;/em&gt; di difficile comprensione e poco SEO.&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt; &lt;span style="color:#0000FF"&gt;Public&lt;/span&gt; &lt;span style="color:#0000FF"&gt;Class&lt;/span&gt; Global_asax
    &lt;span style="color:#0000FF"&gt;Inherits&lt;/span&gt; System.Web.HttpApplication

    &lt;span style="color:#0000FF"&gt;Sub&lt;/span&gt; Application_Start(&lt;span style="color:#0000FF"&gt;ByVal&lt;/span&gt; sender &lt;span style="color:#0000FF"&gt;As&lt;/span&gt; &lt;span style="color:#0000FF"&gt;Object&lt;/span&gt;, &lt;span style="color:#0000FF"&gt;ByVal&lt;/span&gt; e &lt;span style="color:#0000FF"&gt;As&lt;/span&gt; EventArgs)

        RouteTable.Routes.Add(&lt;span style="color:#0000FF"&gt;New&lt;/span&gt; ServiceRoute(&amp;amp;quot;products&amp;amp;quot;, &lt;span style="color:#0000FF"&gt;New&lt;/span&gt; DataServiceHostFactory(), &lt;span style="color:#0000FF"&gt;GetType&lt;/span&gt;(WcfDataService1)))

    &lt;span style="color:#0000FF"&gt;End&lt;/span&gt; &lt;span style="color:#0000FF"&gt;Sub&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Con queste poche righe possiamo richiamare il servizio con l'URI &lt;em&gt;http://localhost:41874/Products/MiaOperazione&lt;/em&gt;. Molto meglio :-)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/ASP.NET/" rel="tag"&gt;ASP.NET&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/ASP.NET_4.0/" rel="tag"&gt;ASP.NET 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/ASP.NET_4.0_Guida_completa/" rel="tag"&gt;ASP.NET 4.0 Guida completa&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/ASP.NET_MVC/" rel="tag"&gt;ASP.NET MVC&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/SEO/" rel="tag"&gt;SEO&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/WCF_Data_Services/" rel="tag"&gt;WCF Data Services&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2605/Routing-Massima-Potenza.aspx"&gt;&lt;em&gt;Routing alla massima potenza&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 3.5, .NET Framework 4.0, ASP.NET, ASP.NET 4.0, ASP.NET 4.0 Guida completa, ASP.NET MVC, SEO, WCF Data Services</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2605/Routing-Massima-Potenza.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2605/Routing-Massima-Potenza.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2605.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2605</trackback:ping></item><item><title>Open Data Protocol e WCF Data Services</title><link>http://blogs.aspitalia.com/ricciolo/post2604/Open-Data-Protocol-WCF-Data-Services.aspx</link><pubDate>Fri, 02 Apr 2010 13:59:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2604" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;E' un po' che non scrivo nel blog e me ne scuso. In generale cerco sempre di dare qualcosa di più rispetto ad un semplice link e sebbene ho scritto poco in questo blog, potete trovare il frutto delle mie esperienze negli script che settimanalmente sforno. Spero che questo sia l'inizio di una serie infinita di post :-)&lt;/p&gt; &lt;p&gt;Dopo questa premessa vorrei porre l'attenzione su un nuovo modo di rendere fruibili le informazioni mediante HTTP. Microsoft sta infatti spingendo molto sull'&lt;a target="_blank" href="http://www.odata.org/"&gt;Open Data Protocol&lt;/a&gt; e perfino al &lt;strong&gt;MIX&lt;/strong&gt; ha mostrato una demo che mostrava come tramite &lt;strong&gt;REST&lt;/strong&gt; si possa interrogare il database di netflix. Con &lt;strong&gt;OData&lt;/strong&gt; si vuole spingere anche le altre piattoforme ad implementare un modo univoco per interrogare database tramite HTTP e ottenere risposte in formato &lt;strong&gt;AtomPub&lt;/strong&gt; o &lt;strong&gt;Json&lt;/strong&gt;. Ci sono già librerie per PHP, Java e ObjectC e di fatto stanno rendendo standard quelli che una volta erano conosciuti con il nome di ADO.NET Data Services e poi ribattezzati WCF Data Services, perché di fatto sono dei servizi WCF preconfezionati che permettono le classiche operazioni CRUD sui dati. Li abbiamo trattati e li tratteremo ancora in WinFXItalia.com e SilverlighItalia.com, e potete trovare materiale a riguardo &lt;a target="_blank" href="http://tags.aspitalia.com/WCF_Data_Services/"&gt;qua&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Le specifiche ora sono giunte alla versione 2 e in esse sono cambiati alcuni modi di formattazione delle risposte, soprattutto per i tipi complessi. Tale versione è implementata dal &lt;strong&gt;.NET Framework 4.0&lt;/strong&gt; e quindi dobbiamo aspettare ancora un pochetto, soprattutto perchè la versione 3.5 presenta molteplici known issue.&lt;/p&gt; &lt;p&gt;Parecchio tempo fa &lt;a target="_blank" href="http://blogs.aspitalia.com/ricciolo/post2256/Evoluzioni-Web-Capisco.aspx"&gt;avevo manifestato&lt;/a&gt; le mie perplessità su questa moda REST/POX e presentato i limiti di queste tecnologie che sono stati in parte colmati. Ad esempio non mi è mai piaciuto che io mi debba leggere un documento che mi spieghi come è fatto l'XML che ottengo in risposta o quali sono gli URI da chiamare. Guarda caso OData definisce questi aspetti e li uniforma. Inoltre se abbiamo un servizio OData possiamo invocare l'URI &lt;em&gt;http://localhost:41874/WcfDataService1.svc/$metadata&lt;/em&gt; e ottenere in risposta un XML che definisce il container e le entità. Questo ci permette di aprire Visual Studio e tramite 'add service reference' referenziare un servizio OData. Quello che otteniamo è un wrapper che attraverso &lt;strong&gt;IQueryable&lt;/strong&gt; ci permette di creare query e tradurle automaticamente in URI, come da &lt;a target="_blank" href="http://www.odata.org/developers/protocols/uri-conventions"&gt;queste&lt;/a&gt; specifiche.&lt;/p&gt; &lt;p&gt;Tutto questo è molto bello, ma sa di già visto e sembra l'ennesimo tentativo di cercare di spingere all'uso di uno standard. I metadati di OData hanno una grossa similitudine con il &lt;strong&gt;WSDL&lt;/strong&gt; e con tutte le altre specifiche &lt;strong&gt;WS-*&lt;/strong&gt; utilizzate per i servizi basati su SOAP. La sensazione è che si voglia semplificare le specifiche e il protocollo per favorirne l'adozione, ma così facendo ovviamente si lasciano irrisolti molte cose. OData non è infatti paragonabile alle funzionalità offerte da WS-* in termini di sicurezza, gestione degli errori e delle transazioni, routing e indipendenza dal mezzo.&lt;/p&gt; &lt;p&gt;Quindi semplicemente le due tecnologie (OData, WS-*) non sono in concorrenza, ma semplicemente coprono scopi diversi. Per questo motivo nel capitolo del &lt;a target="_blank" href="http://g.aspitalia.com/landings/hoepli.aspx"&gt;libro su VB e C#&lt;/a&gt; che ho dedicato a WCF, ho affrontato questa tecnologia in modo da analizzare come questa si presta sia per servizi classici SOAP, sia per servizi OData e a quest'ultimi ho dedicato un'ampia finestra.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/C#_4_Guida_completa/" rel="tag"&gt;C# 4 Guida completa&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Visual_Basic_2010_Guida_completa/" rel="tag"&gt;Visual Basic 2010 Guida completa&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/WCF_Data_Services/" rel="tag"&gt;WCF Data Services&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Windows_Communication_Foundation/" rel="tag"&gt;Windows Communication Foundation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2604/Open-Data-Protocol-WCF-Data-Services.aspx"&gt;&lt;em&gt;Open Data Protocol e WCF Data Services&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4.0, C# 4 Guida completa, Visual Basic 2010 Guida completa, WCF Data Services, Windows Communication Foundation</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2604/Open-Data-Protocol-WCF-Data-Services.aspx</guid><slash:comments>2</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2604/Open-Data-Protocol-WCF-Data-Services.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2604.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2604</trackback:ping></item><item><title>MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010</title><link>http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx</link><pubDate>Thu, 07 Jan 2010 12:58:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2581" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Come promisi parecchio&lt;a href="http://blogs.aspitalia.com/ricciolo/post2483/MetadataDiffViewer-Differenze-Framework.aspx"&gt; tempo fa&lt;/a&gt;, sto mantenendo il &lt;a href="http://lab.ricciolo.aspitalia.com/metadatadiffviewer/metadatadiffviewer.html"&gt;MetadataDiffViewer&lt;/a&gt;, il tool realizzato in &lt;strong&gt;Silverlight&lt;/strong&gt; che permette di visualizzare le differenze tra le versioni dei framework.&lt;/p&gt;&lt;p&gt;Ho aggiornato prima di tutto il metodo di download dei metadati rendendolo più veloce e richiedendo meno spazio nello storage. Ora richiede la versione 3.0 di Silverlight e supporta il mouse wheel.&lt;/p&gt;&lt;p&gt;Anche i metadati sono stati aggiornati per supportare il .NET Framework 4.0 Beta 2, Silverlight 4.0 Beta 1 e Sharepoint 2010, comparati con le relative precedenti versioni.&lt;/p&gt;&lt;p&gt;Spero possa esservi utile per i vostri studi.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_2.0/" rel="tag"&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.0/" rel="tag"&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_3.5/" rel="tag"&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/SharePoint/" rel="tag"&gt;SharePoint&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx"&gt;&lt;em&gt;MetadataDiffViewer: aggiornato al .NET Framework 4.0, Silverlight 4.0 e Sharepoint 2010&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET, .NET Framework, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4.0, SharePoint</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx</guid><slash:comments>3</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2581/MetadataDiffViewer-Aggiornato-.NET-Framework-4.0-Silverlight-4.0-Sharepoint.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2581.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2581</trackback:ping></item><item><title>Silverlight - Real time audio peak meter </title><link>http://blogs.aspitalia.com/ricciolo/post2511/Silverlight-Real-Time-Audio-Peak-Meter.aspx</link><pubDate>Sun, 31 May 2009 09:14:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2511" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;In un &lt;a href="http://blogs.aspitalia.com/ricciolo/post2506/Silverlight-Audio-Peak-Meter.aspx"&gt;post&lt;/a&gt; precedente ho mostrato di come si può realizzare un misuratore di picchi per l'audio di un &lt;b&gt;MediaElement&lt;/b&gt; precalcolandoli con un'applicazione console. Ovviamente questa non è la prassi normale di tutti i lettori normali, dove il calcolo della FFT applicata ai samples avviene in real time, man mano che questi vengono renderizzati sulla periferica audio.&lt;/p&gt;&lt;p&gt;Da Silverlight 2.0 sull'oggetto MediaElement&amp;#xa0;è presente un metodo SetSource che accetta uno Stream oppure un'oggetto &lt;b&gt;MediaStreamSource&lt;/b&gt;. Questa classe ha dei metodi che MediaElement chiama, come OpenMediaAsync, GetSampleAsync, SeekAsync per chiederci di aprire la sorgente, di restituirgli gruppi di samples o di posizionarci ad uno specifico timestamp. Con i metodi ReportOpenMediaCompleted, ReportGetSampleCompleted e ReportSeekCompleted non si fa altro che notificargli l'avvenuta operazione e ciclicamente mandargli pacchetti audio/video.&lt;/p&gt;&lt;p&gt;La brutta notizia è che i samples audio e video devono essere compressi (MP4, WMV) e quindi quello che noi possiamo fare è solo fare da tramite per fonire tracce audio e video con i protocolli che vogliamo: RTP, UPNP, streaming custom. Questa è una brutta notizia perché per applicare la FFT occorre avere i samples grezzi, già decodificati. L'oggetto MediaElement non permette di caricare file &lt;b&gt;WAV&lt;/b&gt; direttamente, ma il MediaStreamSouce permette invece di passare anche i samples raw, che il file WAV appunto contiene. Sebbene si potrebbe scrivere un decoder MP3, non sono così pazzo da farlo :-), perciò ho scelto di creare un file &lt;b&gt;WavMediaStreamSource&lt;/b&gt; che carica tramite WebRequest un file wav e&amp;#xa0;legge&amp;#xa0;l'header per conoscere il numero di canali, i samples al secondo (solitamente 44100) e i bit (8/16). L'implementazione poi non fa altro che rigirare i byte al MediaElement.&lt;/p&gt;&lt;p&gt;Ho portato poi l'algoritmo FFT e di calcolo dei picchi sulla mia libreria Silverlight e diviso il controllo del post precedente in due parti: &lt;b&gt;DataAudioPeakMeter&lt;/b&gt; e &lt;b&gt;SamplesAudioPeakMeter&lt;/b&gt;. Il primo lavora con il file dat precalcolato e funziona con tutti i formati supportati da SL. Il secondo lavora solo con i file WAV, ma funziona in real time. Entrambi poi fanno uso della &lt;b&gt;BarVisualization&lt;/b&gt; per l'animazione.&lt;/p&gt;&lt;p&gt;L'utilizzo è piuttosto semplice:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;MediaElement&lt;/span&gt; &lt;span style="color:#FF0000"&gt;AutoPlay&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;False&amp;quot;&lt;/span&gt;
              &lt;span style="color:#FF0000"&gt;x&lt;/span&gt;:&lt;span style="color:#FF0000"&gt;Name&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;media&amp;quot;&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;

&lt;span style="color:#008000"&gt;&amp;lt;!-- Visualization --&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;SamplesAudioPeakMeter&lt;/span&gt; &lt;span style="color:#FF0000"&gt;x&lt;/span&gt;:&lt;span style="color:#FF0000"&gt;Name&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;sa&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;BarVisualization&lt;/span&gt; &lt;span style="color:#FF0000"&gt;BarSegmentHeight&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;4&amp;quot;&lt;/span&gt;
        &lt;span style="color:#FF0000"&gt;BarMargin&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;
        &lt;span style="color:#FF0000"&gt;BarSegmentMargin&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;
        &lt;span style="color:#FF0000"&gt;StrokeBrush&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;Yellow&amp;quot;&lt;/span&gt;
        &lt;span style="color:#FF0000"&gt;StrokeThickness&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;BarVisualization.BarBrush&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;LinearGradientBrush&lt;/span&gt; &lt;span style="color:#FF0000"&gt;StartPoint&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;0,0&amp;quot;&lt;/span&gt; &lt;span style="color:#FF0000"&gt;EndPoint&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;0,1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;GradientStop&lt;/span&gt; &lt;span style="color:#FF0000"&gt;Offset&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;
                              &lt;span style="color:#FF0000"&gt;Color&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span style="color:#0000FF"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000"&gt;GradientStop&lt;/span&gt; &lt;span style="color:#FF0000"&gt;Offset&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;
                              &lt;span style="color:#FF0000"&gt;Color&lt;/span&gt;=&lt;span style="color:#0000FF"&gt;&amp;quot;Blue&amp;quot;&lt;/span&gt; &lt;span style="color:#0000FF"&gt;/&amp;gt;&lt;/span&gt;

            &lt;span style="color:#0000FF"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000"&gt;LinearGradientBrush&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
        &lt;span style="color:#0000FF"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;BarVisualization.BarBrush&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000FF"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;BarVisualization&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000FF"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#C71585"&gt;a&lt;/span&gt;:&lt;span style="color:#800000"&gt;SamplesAudioPeakMeter&lt;/span&gt;&lt;span style="color:#0000FF"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Da codice poi dobbiamo legare la sorgente wav sia al MediaElement che al SamplesAudioPeakMeter:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;WavMediaStreamSource source = &lt;span style="color:#0000FF"&gt;new&lt;/span&gt; WavMediaStreamSource(&lt;span style="color:#0000FF"&gt;new&lt;/span&gt; Uri(&amp;quot;&lt;span style="color:#8B0000"&gt;test1.wav&lt;/span&gt;&amp;quot;, UriKind.RelativeOrAbsolute));
source.Loop = &lt;span style="color:#0000FF"&gt;true&lt;/span&gt;;

&lt;span style="color:#008000"&gt;// Binding Source -&amp;gt; Visualization&lt;/span&gt;
sa.SetSource(source);
&lt;span style="color:#008000"&gt;// Binding Source -&amp;gt; MediaElement&lt;/span&gt;
media.SetSource(source);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ed ecco il risultato:&lt;/p&gt;
&lt;img src="http://blogs.aspitalia.com/img/Ricciolo/fft.png" /&gt;
&lt;p&gt;Ovviamente i file wav sono di grandi dimensioni quindi questa tecnica è adatta per file di piccola di dimensione sulla quale fare loop, ma meglio di niente :-). Poi speriamo che magari nella RTM di Silverlight 3.0 ci sia la possibilità di accedere ai samples già decodificati.&lt;/p&gt;
&lt;p&gt;Infine le performance: escludendo l'animazione sono rimasto piuttosto colpito. La mia CPU resta su un 2% per calcolare FFT e picchi. Includendo l'animazione si arriva poi ad un 25/30%, ma va considerato che SL tenta sempre di andare al massimo di frame rate per l'esecuzione delle animazioni.&lt;br/&gt;Presto metterò i sorgenti: promesso!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_-_animazioni/" rel="tag"&gt;Silverlight - animazioni&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_2.0/" rel="tag"&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2511/Silverlight-Real-Time-Audio-Peak-Meter.aspx"&gt;&lt;em&gt;Silverlight - Real time audio peak meter &lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Silverlight, Silverlight - animazioni, Silverlight 2.0, XAML</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2511/Silverlight-Real-Time-Audio-Peak-Meter.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2511/Silverlight-Real-Time-Audio-Peak-Meter.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2511.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2511</trackback:ping></item><item><title>Salvare immagini Bitmap con Silverlight 3.0</title><link>http://blogs.aspitalia.com/ricciolo/post2510/Salvare-Immagini-Bitmap-Silverlight-3.0.aspx</link><pubDate>Fri, 29 May 2009 17:56:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2510" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;In &lt;strong&gt;Silverlight 3.0&lt;/strong&gt; è stato aggiunta la possibilità di salvare file in locale attraverso la &lt;strong&gt;SaveFileDialog&lt;/strong&gt;. Per motivi di sicurezza, questa può essere visualizzata solo all'interno di un evento scatenato dall'utente (pressione del pulsante, ecc)&amp;#xa0;mentre attraverso OpenFile è possibile poi aprire uno Stream per la scrittura sulla quale è possibile scrivere qualsiasi cosa.&lt;/p&gt;&lt;p&gt;In una discussione con &lt;a href="http://blogs.aspitalia.com/nostromo/"&gt;Marco&lt;/a&gt; ci è venuto il dubbio se si poteva salvare immagini in locale, ma purtroppo la cosa non è molto semplice da raggiungere. In SL infatti non ci sono API per effettuare encoding ed decoding di immagini ad eccezione del passare uno Stream da visualizzare. Inoltre con &lt;strong&gt;WriteableBitmap&lt;/strong&gt; è stata aggiunta la possibilità di caricare uno Stream o di renderizzare un &lt;strong&gt;UIElement&lt;/strong&gt; su un'immagine, ma poi non è possibile accedere ai byte. Insomma, se si ha un'immagine già codificata in JPEG/PNG basta semplicemente travasare lo Stream sorgente verso il file locale, altrimenti se si ha solo i byte grezzi dell'immagine occorre scriversi il motore di encoding e di creazione del contenitore.&lt;/p&gt;&lt;p&gt;Per fortuna c'è il buon vecchio file &lt;strong&gt;BMP&lt;/strong&gt;, la cui definizione si può trovare &lt;a href="http://en.wikipedia.org/wiki/BMP_file_format"&gt;qui&lt;/a&gt;, che è abbastanza semplice da creare&amp;#xa0;e a parte dover accodare i byte dell'immagine dal basso verso l'altro, non necessita di algoritmi di compressione. Ovviamente il file risultante è di grandi dimensioni, ma non dev'essere trasportato in rete, ma bensì salvato direttamente in locale. Ho scritto quindi un &lt;strong&gt;BitmapEncoder&lt;/strong&gt; e un BitmapFrame per salvare un'immagine in BMP, lo trovate completo di sorgente &lt;a href="http://lab.aspitalia.com/Ricciolo/Downloads/SLSaveBitmap.zip"&gt;qua&lt;/a&gt;. L'esempio allegato genera un'immagine con un algoritmo e la mostra anche attraverso un WriteableBitmap.&lt;/p&gt;&lt;p&gt;&lt;img align="baseline" src="http://blogs.aspitalia.com/img/Ricciolo/SLBitmap.jpg" border="0" hspace="0" complete="true" complete="true" /&gt;&lt;/p&gt;&lt;p&gt;Purtroppo non serve a tantissimo, perché attualmente la WriteableBitmap non permette di accedere ai pixel e quindi non è possibile salvare screenshot effettuati sugli elementi. Potenzialmente si può creare qualsiasi file, ma ovviamente non è semplice doversi riscrivere librerie di creazione di file, non potendosi appoggiare a oggetti COM.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/Silverlight/" rel="tag"&gt;Silverlight&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/XAML/" rel="tag"&gt;XAML&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/Silverlight_3.0/" rel="tag"&gt;Silverlight 3.0&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2510/Salvare-Immagini-Bitmap-Silverlight-3.0.aspx"&gt;&lt;em&gt;Salvare immagini Bitmap con Silverlight 3.0&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>Silverlight, XAML, Silverlight 3.0</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2510/Salvare-Immagini-Bitmap-Silverlight-3.0.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2510/Salvare-Immagini-Bitmap-Silverlight-3.0.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2510.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2510</trackback:ping></item><item><title>.NET Framework 4.0 beta 1: Tuple</title><link>http://blogs.aspitalia.com/ricciolo/post2509/.NET-Framework-4.0-Beta-1-Tuple.aspx</link><pubDate>Wed, 27 May 2009 04:00:00 GMT</pubDate><description>&lt;img src="http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2509" border="0" style="width:1px; height:1px;" /&gt;&lt;p&gt;Altro post per un&amp;#39;altra novità del .NET Framework 4.0: le classi &lt;b&gt;Tuple&lt;/b&gt;. In pratica sono delle classi generiche con tanti argomenti generici quanti sono le relative proprietà che esse espongono.&lt;/p&gt;
&lt;p&gt;Per esempio Tuple&amp;lt;T1, T2&amp;gt; ha una proprietà Item1 di tipo T1 e una proprietà Item2 di tipo T2. Ci vengono molto comode per quelle volte che nei nostri algoritmi, per velocizzare la scrittura del codice (o per pigrizia :-) ), abbiamo bisogno di una classe che faccia da repository dei valori. Inoltre la loro caratteristica è di implementare GetHashCode, Equals e l&amp;#39;interfaccia &lt;b&gt;IComparable&lt;/b&gt;, &lt;b&gt;IStructuralEquatable&lt;/b&gt; (nuova in .NET 4.0) e &lt;b&gt;IStructuralComparable&lt;/b&gt; (nuova in .NET 4.0) in modo che a parità dei valori, due istanze di Tuple diverse risultino uguali. Si comportano quindi come un valore atomico e sono l&amp;#39;ideale per essere utilizzate come chiavi per dictionary o per hash set.&lt;/p&gt;
&lt;p&gt;Per capirci quindi:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;var t = Tuple.Create&amp;lt;Int32, String&amp;gt;(2, &amp;quot;&lt;span style="color:#8B0000"&gt;ciao&lt;/span&gt;&amp;quot;);
var t2 = Tuple.Create&amp;lt;Int32, String&amp;gt;(2, &amp;quot;&lt;span style="color:#8B0000"&gt;ciao&lt;/span&gt;&amp;quot;);

Console.WriteLine(t.Item2);
Console.WriteLine(&amp;quot;&lt;span style="color:#8B0000"&gt;Reference equals: {0}&lt;/span&gt;&amp;quot;, Object.ReferenceEquals(t, t2));
Console.WriteLine(&amp;quot;&lt;span style="color:#8B0000"&gt;Equals: {0}&lt;/span&gt;&amp;quot;, t.Equals(t2));&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;stampa a video:&lt;/p&gt;
&lt;div class="codebox"&gt;&lt;pre&gt;ciao
Reference equals: False
Equals: True&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In effetti c&amp;#39;è una forte somiglianza agli anonymous type sebbene quest&amp;#39;ultimi sono generati dal compilatore e hanno proprietà dal nome che vogliamo. In comune hanno infatti che due istanze diverse, ma con identici valori, risultano uguali se comparati tra loro. Non implementano però IStructuralEquatable, ma non credo che questo sia un problema. Se necessitiamo di lavorare a livello d&amp;#39;interfaccia allora tanto vale restituire una tuple nelle nostre query.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href="http://tags.aspitalia.com/.NET_Framework/" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://tags.aspitalia.com/.NET_Framework_4.0/" rel="tag"&gt;.NET Framework 4.0&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Continua a leggere &lt;a href="http://blogs.aspitalia.com/ricciolo/post2509/.NET-Framework-4.0-Beta-1-Tuple.aspx"&gt;&lt;em&gt;.NET Framework 4.0 beta 1: Tuple&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://www.aspitalia.com/"&gt;(C) 2012 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</description><dc:creator>Cristian &amp;quot;Ricciolo&amp;quot; Civera</dc:creator><category>.NET 4.0, .NET Framework, .NET Framework 4.0</category><guid isPermaLink="true">http://blogs.aspitalia.com/ricciolo/post2509/.NET-Framework-4.0-Beta-1-Tuple.aspx</guid><slash:comments>0</slash:comments><wfw:comment>http://blogs.aspitalia.com/ricciolo/post2509/.NET-Framework-4.0-Beta-1-Tuple.aspx#feedback</wfw:comment><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2509.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2509</trackback:ping></item></channel></rss>
