<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>il blog di Marco Amendola</title>
        <link>http://blogs.ugidotnet.org/marcoamendola/Default.aspx</link>
        <description>problem exists between keyboard and chair</description>
        <language>it</language>
        <copyright>Marco Amendola</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <image>
            <title>il blog di Marco Amendola</title>
            <url>http://blogs.ugidotnet.org/images/RSS2Image.gif</url>
            <link>http://blogs.ugidotnet.org/marcoamendola/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>Le Coroutine sono morte. Lunga vita alle Coroutine.</title>
            <link>http://blogs.ugidotnet.org/marcoamendola/archive/2012/10/17/le-coroutine-sono-morte.-lunga-vita-alle-coroutine.aspx</link>
            <description>&lt;p&gt;Come alcuni di voi possono aver &lt;a href="http://devlicio.us/blogs/rob_eisenberg/archive/2012/08/02/today-all-your-wildest-dreams-come-true.aspx"&gt;già sentito&lt;/a&gt;, Caliburn.Micro è stato recentemente &lt;a href="http://www.markermetro.com/2012/08/technical/caliburn-micro-for-winrt-mvvm-magic-pixie-dust-for-everyone/"&gt;convertito a WinRT&lt;/a&gt; grazie a &lt;a href="https://twitter.com/nigelsampson"&gt;Nigel Sampson&lt;/a&gt; e &lt;a href="https://twitter.com/kpatton"&gt;Keith Patton&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Sia che facciate già sviluppo per Windows 8, sia che stiate lavorando con WPF ed il framework .NET 4.5, è probabile che &lt;strike&gt;siate tutti presi a giocare&lt;/strike&gt; lavorando molto proficuamente con il potente supporto per la programmazione asincrona presente in Visual Studio 2012. (Non ancora? Correte &lt;a href="http://msdn.com/async"&gt;a studiarlo&lt;/a&gt; ORA).&lt;/p&gt;  &lt;p&gt;Per chi ha utilizzato Caliburn e Caliburn.Micro, una forma di programmazione asincrona molto pulita e ordinata era già disponibile sin dal 2009: date un’occhiata a questo &lt;a href="http://devlicio.us/blogs/rob_eisenberg/archive/2009/07/10/asynchronous-execution-animation-and-more-in-mvvm-with-caliburn.aspx"&gt;post di Rob che presenta IResult e le Coroutine&lt;/a&gt;, un anno prima di Async CTP!&lt;/p&gt;  &lt;p&gt;Adesso comunque il paradigma async/await è destinato a diventare di comune utilizzo; significa che IResult e le Coroutine &lt;a href="http://caliburnmicro.codeplex.com/discussions/356766"&gt;sono destinate a diventare superflue&lt;/a&gt;?     &lt;br /&gt;La mia opinione inziale era che potessero essere mantenute solo per compatibilità, ma in realtà si sono dimostrate ancora piuttosto importanti, per una serie di ragioni.&lt;/p&gt;  &lt;h3&gt;Accesso al contesto di esecuzione&lt;/h3&gt;  &lt;p&gt;In numerosi scenari l’azione definita nel ViewModel richiede di ottenere un accesso diretto alla Vies o all’elemento che ha scatenato l’azione stessa.    &lt;br /&gt;L’istanza della View può essere ottenuta usando il metodo &lt;em&gt;GetView&lt;/em&gt; della classe &lt;em&gt;Screen&lt;/em&gt; (o implementando direttamente &lt;em&gt;IViewAware&lt;/em&gt;), ma l’elemento “scatenante” non è altrettanto facile da ottenere.&lt;/p&gt;  &lt;p&gt;Inoltre, mentre in alcuni casi isolati l’utilizzo di un approccio “stile Model-View-Presenter” è l’unica soluzione praticabile, in generale i ViewModel non dovrebbero comandare la UI in maniera diretta, anzi non dovrebbero occuparsi affatto di affari riguardanti la mera presentazione.&lt;/p&gt;  &lt;p&gt;Implementazioni personalizzate di &lt;em&gt;IResult&lt;/em&gt;, invece, consentono un facile accesso ad un oggetto di tipo &lt;em&gt;ActionExecutionContext&lt;/em&gt;, che raggruppa tutti gli oggetti coinvolti nell’esecuzione di una azione: la View corrente, l’elemento di UI “scatenante”, l’istanza del ViewModel corrente, il metodo invocato, ecc.     &lt;br /&gt;Così, mentre effettivamente creare IResult ad-hoc per ciascuna semplice operazione asincrona è decisamente noioso, utilizzare IResult riusabili per isolare particolari aspetti di UI risulta molto efficace, e aiuta a mantenere pulito il codice del ViewModel.&lt;/p&gt;  &lt;h3&gt;Testabilità&lt;/h3&gt;  &lt;p&gt;E’ assolutamente possibile testare del codice asincrono scritto con &lt;em&gt;async/await&lt;/em&gt;, generalmente rimpiazzando i servizi e le dipendenze con dei mock.     &lt;br /&gt;In altrernativa, utilizzare una coroutine che restituisca &lt;em&gt;IEnumerable&amp;lt;IResult&amp;gt;&lt;/em&gt; consente di testare solamente la sequenza restituita, senza eseguire realmente i passi rappresentati dagli &lt;em&gt;IResult&lt;/em&gt;.&lt;em&gt; &lt;/em&gt;&lt;/p&gt;  &lt;h3&gt;“Contenimento” dell’esecuzione di una azione&lt;/h3&gt;  &lt;p&gt;Caliburn.Micro può mappare (attraverso convenzioni oppure utilizzando una sintassi esplicita) un evento che si verifica all’interno della UI verso la chiamata ad un metodo dalla parte del ViewModel.    &lt;br /&gt;Di conseguenza è molto semplice convertire un semplice metodo &lt;em&gt;void&lt;/em&gt; in un metodo asincrono (&lt;em&gt;async void &lt;/em&gt;oppure &lt;em&gt;async Task&lt;/em&gt;) e lasciare che Caliburn.Micro si occupi del suo &lt;strong&gt;avvio&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Tuttavia non consiglio quiesto approccio: in tal modo, infatti, l’esecuzione dell’azione (dal punto di vista di CM) si esaurisce non appena un oggetto &lt;em&gt;Task&lt;/em&gt; viene instanziato (ed eventualmente restituito dal metodo), mentre l’effettiva esecuzione richede generalmente molto più tempo. Inoltre, eventuali eccezioni scatenate durante l’esecuzione possono rimanere non osservate (vedi  &lt;a href="http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx"&gt;http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx&lt;/a&gt;), poiché l’oggetto task non è più accessibile.&lt;/p&gt;  &lt;p&gt;Per questi motivi ho scritto una semplice estensione che si occupa di queste problematiche; la strategia scelta è quella di personalizzare il codice di invocazione delle action di Caliburn.Micro, in modo da intercettari i metodi asincroni che restituiscano &lt;em&gt;Task&lt;/em&gt; ed ospitarli all’interno di un IResult personalizzato.  &lt;br /&gt;In questo modo è possibile sfuttare semplicemente l’infrastruttura esistente; in particolare, è possibile utilizzare il già presente meccanismo di notifica del completamento delle Coroutine (evento statico &lt;em&gt;Coroutine.Complete&lt;/em&gt;), che fornisce anche informazioni circa eventuali eccezioni verificatesi nel metodo.&lt;/p&gt;  &lt;p&gt;Di seguito il codice dell’estensione:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; AsyncAwaitSupport
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Hook()
    {

        ActionMessage.InvokeAction = context =&amp;gt;
        {

            var values = MessageBinder.DetermineParameters(context, context.Method.GetParameters());
            var returnValue = context.Method.Invoke(context.Target, values);

            var task = returnValue &lt;span class="kwrd"&gt;as&lt;/span&gt; Task;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (task != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                returnValue = &lt;span class="kwrd"&gt;new&lt;/span&gt; TaskResult(task);
            }

            var result = returnValue &lt;span class="kwrd"&gt;as&lt;/span&gt; IResult;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (result != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                returnValue = &lt;span class="kwrd"&gt;new&lt;/span&gt;[] { result };
            }

            var enumerable = returnValue &lt;span class="kwrd"&gt;as&lt;/span&gt; IEnumerable;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (enumerable != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                Coroutine.BeginExecute(enumerable.GetEnumerator(), context);
                &lt;span class="kwrd"&gt;return&lt;/span&gt;;
            }

            var enumerator = returnValue &lt;span class="kwrd"&gt;as&lt;/span&gt; IEnumerator;
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (enumerator != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            {
                Coroutine.BeginExecute(enumerator, context);
                &lt;span class="kwrd"&gt;return&lt;/span&gt;;
            }
        };
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TaskResult : IResult
    {
        Task task;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; TaskResult(Task task)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (task == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"task"&lt;/span&gt;);
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.task = task;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;event&lt;/span&gt; EventHandler Completed = &lt;span class="kwrd"&gt;delegate&lt;/span&gt; { };

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Execute(ActionExecutionContext context)
        {
            task.ContinueWith(t =&amp;gt;
            {
                Completed(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; ResultCompletionEventArgs {
                                            WasCancelled = t.IsCanceled,
                                            Error = t.Exception }
                                       );
            });
        }
    }

}&lt;/pre&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;L’estensione viene agganciata durante l’inizializzazione del &lt;em&gt;bootstrapper&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Configure()
{
    &lt;span class="kwrd"&gt;base&lt;/span&gt;.Configure();

    AsyncAwaitSupport.Hook();

    &lt;span class="rem"&gt;//...&lt;/span&gt;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;Una volta inserito il codice precedente, posso convertire il seguente codice (esempio preso da &lt;em&gt;CoroutineViewModel.cs &lt;/em&gt;all’interno di &lt;em&gt;Caliburn.Micro.WinRT.Sample)&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerable ExecuteCoroutine()
{
    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; VisualStateResult(&lt;span class="str"&gt;"Loading"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; DelayResult(2000);
    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; VisualStateResult(&lt;span class="str"&gt;"LoadingComplete"&lt;/span&gt;);
    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; MessageDialogResult(&lt;span class="str"&gt;"This was executed from a custom IResult, MessageDialogResult."&lt;/span&gt;, &lt;span class="str"&gt;"IResult Coroutines"&lt;/span&gt;);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;in qualcosa di questo tipo:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; async Task ExecuteTask()
{
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetVisualStateOnView(&lt;span class="str"&gt;"Loading"&lt;/span&gt;);

    await Task.Delay(2000);

    &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetVisualStateOnView(&lt;span class="str"&gt;"LoadingComplete"&lt;/span&gt;);

    &lt;span class="rem"&gt;//This is just a sample: I don't actually recommend calling UI code from here in real code.&lt;/span&gt;
    var dialog = &lt;span class="kwrd"&gt;new&lt;/span&gt; Windows.UI.Popups.MessageDialog(&lt;span class="str"&gt;"This was executed with a regular MessageDialog."&lt;/span&gt;, &lt;span class="str"&gt;"Async/await"&lt;/span&gt;);
    await dialog.ShowAsync();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;&lt;![CDATA[





.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;&lt;em&gt;[Tradotta dalla &lt;/em&gt;&lt;a href="http://marcoamendola.wordpress.com/2012/10/16/coroutines-are-dead-long-live-coroutines/"&gt;&lt;em&gt;versione inglese&lt;/em&gt;&lt;/a&gt;&lt;em&gt;]&lt;/em&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/marcoamendola/aggbug/101273.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Marco Amendola</dc:creator>
            <guid>http://blogs.ugidotnet.org/marcoamendola/archive/2012/10/17/le-coroutine-sono-morte.-lunga-vita-alle-coroutine.aspx</guid>
            <pubDate>Wed, 17 Oct 2012 01:10:38 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/marcoamendola/archive/2012/10/17/le-coroutine-sono-morte.-lunga-vita-alle-coroutine.aspx#feedback</comments>
            <slash:comments>601</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/marcoamendola/comments/commentRss/101273.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/marcoamendola/services/trackbacks/101273.aspx</trackback:ping>
        </item>
        <item>
            <title>Hello world</title>
            <link>http://blogs.ugidotnet.org/marcoamendola/archive/2010/12/06/hello-world.aspx</link>
            <description>&lt;p&gt;Salve a tutti. Mi chiamo Marco Amendola e sono un nuovo inquilino di questo interessante spazio di approfondimento e condivisione.&lt;/p&gt;  &lt;p&gt;Mi occupo, come immagino la maggior parte di voi, di progettare e sviluppare software su piattaforma Microsoft .NET.    &lt;br /&gt;Dopo aver lavorato a lungo su applicazioni web, negli ultimi anni ho utilizzato prevalentemente tecnologie WPF e Silverlight.     &lt;br /&gt;Sono particolarmente interessato al design Object Oriented e allo studio dell'architettura del software.&lt;/p&gt;  &lt;p&gt;Dalla fine dello scorso anno sto collaborando al progetto &lt;a href="http:\\caliburn.codeplex.com"&gt;Caliburn&lt;/a&gt;, un framework MVVM (e non solo...) per applicazioni WPF, Silverlight e &lt;a href="http://caliburnmicro.codeplex.com/"&gt;WP7&lt;/a&gt;.     &lt;br /&gt;E' il primo progetto open source a cui contribuisco, e devo dire che si è  rivelata un'esperienza davvero entusiasmante ed istruttiva, seppure abbastanza impegnativa.&lt;/p&gt;  &lt;p&gt;Da alcuni mesi, insieme a &lt;a href="http://domusdotnet.org/chi-siamo.aspx"&gt;questo gruppo&lt;/a&gt; di &lt;strike&gt;pazzi scatenati&lt;/strike&gt; seriosi professionisti, con cui condivido la passione per lo sviluppo di software, partecipo alla community &lt;a href="http://domusdotnet.org"&gt;DomusDotNet&lt;/a&gt;.     &lt;br /&gt;In questo periodo divertente e intenso ho avuto modo di conoscere la realtà veramente stimolante delle community tecniche locali, che spero di riuscire a seguire con sempre maggior frequenza.&lt;/p&gt;  &lt;p&gt;E' principalmente questo, oltre al provvidenziale incoraggiamento di &lt;a href="http://blogs.ugidotnet.org/nick60"&gt;Nick&lt;/a&gt;, il motivo che mi ha spinto ad aprire questo blog; a questo proposito colgo l'occasione per ringraziare &lt;a href="http://blogs.ugidotnet.org/pape"&gt;Andrea&lt;/a&gt; per aver provveduto prontamente a creare il mio account, scusandomi per aver aggiunto un ulteriore task alla sua &lt;a href="http://blogs.ugidotnet.org/pape/archive/2010/11/30/il-mio-lavoro-rispondere-alle-e-mail.aspx"&gt;nutrita inbox&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Non so ancora bene cosa scriverò: penso che parlerò di Silverlight, MVVM e Caliburn.Micro, che è quello di cui mi occupo quotidianamente, seguendo un po' la linea del &lt;a href="http://marcoamendola.wordpress.com"&gt;mio blog attuale&lt;/a&gt;; quello di cui sono sicuro è che sarà un blog piuttosto "lento" perché il lavoro mi lascia davvero poco tempo libero.     &lt;br /&gt;Spero comunque di riuscire a contribuire a questo spazio con qualche argomento interessante.&lt;/p&gt;  &lt;p&gt;A presto!&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/marcoamendola/aggbug/99535.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Marco Amendola</dc:creator>
            <guid>http://blogs.ugidotnet.org/marcoamendola/archive/2010/12/06/hello-world.aspx</guid>
            <pubDate>Mon, 06 Dec 2010 11:50:04 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/marcoamendola/archive/2010/12/06/hello-world.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/marcoamendola/comments/commentRss/99535.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/marcoamendola/services/trackbacks/99535.aspx</trackback:ping>
        </item>
    </channel>
</rss>