<?xml version="1.0" encoding="Windows-1252"?><feed version="0.3" 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/" xmlns="http://purl.org/atom/ns#" xml:lang="it-it"><title>Ricciolo.NET - Il blog di Cristian "Ricciolo" Civera</title><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/" /><tagline type="text/html">Ricciolo.NET - Il blog di Cristian &quot;Ricciolo&quot; Civera</tagline><id>http://blogs.aspitalia.com/ricciolo/</id><generator url="http://feed.aspitalia.com/" version="ASPItalia.com">feed.ASPItalia.com 'Weyoh' 4.8.818</generator><author><name>Ricciolo.NET - Il blog di Cristian &quot;Ricciolo&quot; Civera</name><url>http://blogs.aspitalia.com/ricciolo/</url></author><modified>2008-08-22T05:14:05+00:00</modified><entry><title>Lambda Expression in Windows Presentation Foundation</title><id>http://blogs.aspitalia.com/ricciolo/post2356/Lambda-Expression-Windows-Presentation-Foundation.aspx</id><created>2008-08-07T16:49:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2356' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Preso da &lt;strong&gt;LINQ&lt;/strong&gt;, Expression e compagnia bella, mi &#232; venuto in mente di provare ad applicare LINQ anche in &lt;strong&gt;WPF&lt;/strong&gt;, la mia primissima passione. Ho pensato al &lt;strong&gt;Binding&lt;/strong&gt;, che &#232; bellissimo, ma spesso mi trovo a dover usare converter che, anche se molto stupidi, richiedono di creare una classe che implementi &lt;strong&gt;IValueConverter&lt;/strong&gt;, referenziarla e instanziarla nel markup.&lt;/p&gt;&lt;p&gt;Ho creato quindi una &lt;strong&gt;MarkupExtension&lt;/strong&gt; personalizzata che imposti in fase di inizializzazione un converter basato su espressioni inserite direttamente nel markup. Partiamo quindi dalla fine; l'utilizzo &#232; il seguente e permette di mettere in maiuscolo ci&#242; che &#232; stato immesso nella TextBox txt:&lt;/p&gt;&lt;p&gt;&lt;code&gt;&amp;lt;TextBox x:Name=&amp;quot;txt&amp;quot; Text=&amp;quot;Testo&amp;quot; /&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;TextBlock&lt;br /&gt;Text=&amp;quot;{Binding Path=Text,ElementName=txt,&lt;br /&gt;Converter={m:Expression value.ToString().ToUpper(culture)}}&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Creare una MarkupExtension &#232; abbastanza semplice. Basta ereditare dalla classe e implementare ProvideValue, chiamato in fase di inizializzazione del markup. La mia implementazione effettua il parsing dell'espressione, ottiene un delegate e la passa ad una nuova istanza di una mia &lt;strong&gt;ExpressionValueConverter&lt;/strong&gt; che implementa IValueConverter e semplicemente chiama questo delegate:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public delegate object ExpressionConverterDelegate(object value, object target, Type targetType, object parameter, CultureInfo culture);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Il parsing dell'espressione l'ho poi affidato ad una serie di classi contenute nell'esempio &lt;strong&gt;DynamicLinq&lt;/strong&gt; presente nel SDK del .NET Framework 3.5. Fatte alcune piccole modifiche, chiamando DynamicExpression.ParseLambda possiamo ottenere una lambda expression, in questo caso con la nostra firma, da poter compilare cos&#236; da ottenere il delegate:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public override object ProvideValue(IServiceProvider serviceProvider)&lt;br /&gt;{&lt;br /&gt;IProvideValueTarget provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));&lt;/p&gt;&lt;p&gt;LambdaExpression le = DynamicExpression.ParseLambda&amp;lt;ExpressionConverterDelegate&amp;gt;(&lt;br /&gt;new ParameterExpression[] { &lt;br /&gt;Expression.Parameter(typeof(object), &amp;quot;value&amp;quot;),&lt;br /&gt;Expression.Parameter(typeof(object), &amp;quot;target&amp;quot;),&lt;br /&gt;Expression.Parameter(typeof(Type), &amp;quot;targetType&amp;quot;),&lt;br /&gt;Expression.Parameter(typeof(object), &amp;quot;parameter&amp;quot;), &lt;br /&gt;Expression.Parameter(typeof(CultureInfo), &amp;quot;culture&amp;quot;)&lt;br /&gt;},&lt;br /&gt;typeof(object),&lt;br /&gt;this.ConvertExpression,&lt;br /&gt;null);&lt;/p&gt;&lt;p&gt;ExpressionConverterDelegate converter = (ExpressionConverterDelegate)le.Compile();&lt;br /&gt;return new ExpressionValueConverter(provideValueTarget.TargetObject, converter);&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Figo no? Le performance poi una volta creato il delegate sono le medesime di una normale classe.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/Ricciolo/WPFExpression.zip&quot;&gt;Qui&lt;/a&gt; il codice sorgente.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_4.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 4.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Windows_Presentation_Foundation/&quot; rel=&quot;tag&quot;&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2356/Lambda-Expression-Windows-Presentation-Foundation.aspx"/><issued>2008-08-07T18:49:00+00:00</issued><modified>2008-08-07T18:49:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2356/Lambda-Expression-Windows-Presentation-Foundation.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2356.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2356</trackback:ping></entry><entry><title>LINQ to reflection - Parte due</title><id>http://blogs.aspitalia.com/ricciolo/post2336/LINQ-Reflection-Parte.aspx</id><created>2008-07-20T06:00:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2336' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Qualche giorno fa ho &lt;a href=&quot;http://blogs.aspitalia.com/ricciolo/post2335/LINQ-Reflection.aspx&quot;&gt;parlato&lt;/a&gt; di come &#232; possibile generare &lt;strong&gt;IL&lt;/strong&gt; a runtime per velocizzare le operazioni che solitamente si effettuano via reflection.&lt;/p&gt;&lt;p&gt;Oltre alla FastCreateInstance ho implementato una FastSetValue. In questo caso il metodo dinamico generato non fa altro che ricevere l'istanza e&#160;il valore impostandola sulla propriet&#224;. Ecco il codice dell'extension method:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static void FastSetValue(this PropertyInfo property, object obj, object value)&lt;br /&gt;{&lt;br /&gt;&#160;&#160;&#160; if (property == null)&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; throw new ArgumentNullException(&amp;quot;property&amp;quot;);&lt;/p&gt;&lt;p&gt;&#160;&#160;&#160; SetValueInvoker invoker = (SetValueInvoker)setValueInvokers[property];&lt;br /&gt;&#160;&#160;&#160; if (invoker == null)&lt;br /&gt;&#160;&#160;&#160; {&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; DynamicMethod method = new DynamicMethod(property.Name, null, new Type[] { typeof(object), typeof(object) }, typeof(object), true);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ILGenerator il = method.GetILGenerator();&lt;/p&gt;&lt;p&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // ((Tipo)oggetto).Proprieta = valore&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Ldarg_0);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Castclass, property.DeclaringType);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Ldarg_1);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (property.PropertyType.IsClass)&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Castclass, property.PropertyType);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; else&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Unbox_Any, property.PropertyType);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.EmitCall(OpCodes.Callvirt, property.GetSetMethod(true), null);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Nop);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; il.Emit(OpCodes.Ret);&lt;/p&gt;&lt;p&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; invoker = (SetValueInvoker)method.CreateDelegate(typeof(SetValueInvoker));&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160; setValueInvokers[property] = invoker;&lt;br /&gt;&#160;&#160;&#160; }&lt;br /&gt;&#160;&#160;&#160; invoker(obj, value);&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;La tecnica &#232; la stessa del FastCreateInstance. Un Hashtable mantiene il delegate specifico per la &lt;strong&gt;PropertyInfo&lt;/strong&gt; e se non c'&#232; crea il codice IL. In questo caso carica nello stack il primo argomento (l'entit&#224;) e ne effettua il cast sul tipo. Poi carica il secondo argomento (il valore da impostare sulla propriet&#224;) e ne effettua il cast se &#232; un tipo di riferimento o l'unboxing se &#232; un tipo di valore (numeri, date, ecc). A questo punto chiama il metodo set_nomepropriet&#224; (le propriet&#224; in .NET non sono altro che metodi con una nomenclatura particolare) che preleva dallo stack i due argomenti inseriti.&lt;/p&gt;&lt;p&gt;Una volta pronto il delegate SetValueInvoker(object obj, object value), poi lo chiamiamo con i parametri ricevuti. Ed ecco il suo utilizzo:&lt;/p&gt;&lt;p&gt;&lt;code&gt;PropertyInfo pi = typeof(Product).GetProperty(&amp;quot;Description&amp;quot;, BindingFlags.Public | BindingFlags.Instance);&lt;br /&gt;Product p = new Product();&lt;br /&gt;pi.FastSetValue(p, &amp;quot;ciao&amp;quot;);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Il risultato &#232; che siamo passati da un'operazione pi&#249; lenta 150 volte (la normale SetValue della PropertyInfo) ad un 15 volte pi&#249; lento&#160;e anche in questo caso&#160;a causa&#160;del costo di ricerca nell'Hashtable e di creazione del metodo alla prima chiamata.&lt;/p&gt;&lt;p&gt;Una nota interessante su &lt;strong&gt;OpCodes.Castclass&lt;/strong&gt;. In realt&#224; questa operazione (obbligatoria quando scriviamo codice in C#) non &#232; indispensabile poich&#233; effettua solo un controllo sul tipo di puntatore presente nello stack. Se omesso, anche se sbagliamo il tipo, il &lt;strong&gt;CLR&lt;/strong&gt; comunque va ad inserire un valore scorretto. Potremmo perfino inserire un numero in una stringa e tutto andrebbe senza problemi fino a quando non chiamiamo un metodo di istanza che fa saltare per aria il CLR :-). Ho preferito comunque lasciare il cast poich&#233; non voglio fidarmi ciecamente del chiamante ed inoltre il costo di tale operazione &#232; minimo e trascurabile.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_2.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2336/LINQ-Reflection-Parte.aspx"/><issued>2008-07-20T08:00:00+00:00</issued><modified>2008-07-20T08:00:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2336/LINQ-Reflection-Parte.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2336.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2336</trackback:ping></entry><entry><title>Eccovi LINQ to reflection</title><id>http://blogs.aspitalia.com/ricciolo/post2335/LINQ-Reflection.aspx</id><created>2008-07-19T20:03:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2335' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Un bel titolo ingannevole per attirarvi a leggere alcuni extension method che ho sviluppato per risolvere in parte le problematiche di performance delle quali ho discusso &lt;a href=&quot;http://blogs.aspitalia.com/ricciolo/post2332/Reflection-Migliorare-Performance.aspx&quot;&gt;qua&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Come avevo accennato, un'opzione pu&#242; essere quella di generare codice dinamico. Per farlo facilmente &lt;strong&gt;LINQ&lt;/strong&gt; include un namespace &lt;strong&gt;System.Linq.Expressions&lt;/strong&gt; dove possiamo rappresentare un'espressione con un modello ad oggetti. Questa classi sono vitali per LINQ to SQL e simili, ma la cosa carina &#232; che la &lt;strong&gt;LambdaExpression&lt;/strong&gt; permette di compilare l'espressione e ottenere un delegate ad essa. In particolare &lt;strong&gt;Expression&amp;lt;TDelegate&amp;gt;&lt;/strong&gt; ci consente di specificare qualsiasi espressione con uno specifico delegate direttamente da codice per poi ottenerne il puntatore con il metodo Compile. Per esempio:&lt;/p&gt;&lt;p&gt;&lt;code&gt;Expression&amp;lt;Func&amp;lt;Product&amp;gt;&amp;gt; ef = () =&amp;gt; new Product();&lt;br /&gt;Func&amp;lt;Product&amp;gt; f = ef.Compile();&lt;br /&gt;Product p = f();&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Il codice precedente rapprenta prima l'espressione per creare una nuova istanza di Product, poi la compila per avere una funzione vera e propria che non vuole nessun parametro, ma il cui tipo di ritorno &#232; Product. Una cosa importantissima &#232; la prima riga: poich&#233; vogliamo un Expression il compilatore genera codice per rappresentare la lamba expression, diversamente dal normale uso che si fa con LINQ to Object, dove viene effettivamente creato un metodo che contiene la lambda.&lt;/p&gt;&lt;p&gt;Quindi questa introduzione per dire che possiamo usare questa caratteristica per generare al volo un metodo che ci permetta di istanziare velocemente un tipo. Ecco quindi l'extension method che ho sviluppato:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static object FastCreateInstance(this Type type)&lt;br /&gt;{&lt;br /&gt;&#160;&#160;&#160;&#160;if (type == null)&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;throw new ArgumentNullException(&amp;quot;type&amp;quot;);&lt;/p&gt;&lt;p&gt;&#160;&#160;&#160;&#160;CreateInstanceInvoker invoker = (CreateInstanceInvoker)createInstanceInvokers[type];&lt;br /&gt;&#160;&#160;&#160;&#160;if (invoker == null)&lt;br /&gt;&#160;&#160;&#160;&#160;{&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;LambdaExpression e = Expression.Lambda(typeof(CreateInstanceInvoker), Expression.New(type), null);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;invoker = (CreateInstanceInvoker)e.Compile();&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;createInstanceInvokers[type] = invoker;&lt;br /&gt;&#160;&#160;&#160;&#160;}&lt;br /&gt;&#160;&#160;&#160;&#160;return invoker();&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In pratica con un &lt;strong&gt;Hashtable&lt;/strong&gt; mantengo una lista di delegate in funzione del tipo e se non c'&#232;, creo una LambdaExpression, la compilo per ottenere il delegate che user&#242; le successive volte. L'utilizzo del metodo poi &#232; semplicissimo:&lt;/p&gt;&lt;p&gt;&lt;code&gt;Product p = typeof(Product).FastCreateInstance();&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Usando questa tecnica i tempi si dimezzano rispetto all'uso di &lt;strong&gt;Activator.CreateInstance&lt;/strong&gt;, seppure mai veloce abbastanza come usare il costruttore direttamente. Il costo dell'operazioni infatti si sposta e in questo caso &#232; dovuto pi&#249; al recupero del delegate in modo thread safe dall'Hashtable.&lt;/p&gt;&lt;p&gt;Cosa fa il metodo Compile? Utilizza la classe &lt;strong&gt;DynamicMethod&lt;/strong&gt; che consente di generare per l'appunto un metodo dinamico, mediante &lt;strong&gt;IL&lt;/strong&gt; per poi darlo in pasto al jitter e renderlo cos&#236; veloce quanto il normale codice. Questa classe esiste dal .NET Framework 2.0 e facilita la definizione di Assembly, Module e Type dinamici, gi&#224; possibile fin dalla versione 1.0. L'unico inconveniente &#232; che bisogna masticare un po' di IL, perci&#242; il metodo FastCreateInstance pu&#242; creare il delegate anche in questo modo:&lt;/p&gt;&lt;p&gt;&lt;code&gt;DynamicMethod method = new DynamicMethod(&amp;quot;method&amp;quot;, typeof(object), new Type[0], typeof(object), true);&lt;br /&gt;ILGenerator il = method.GetILGenerator();&lt;br /&gt;il.Emit(OpCodes.Newobj, type.GetConstructor(new Type[0]));&lt;br /&gt;il.Emit(OpCodes.Ret);&lt;/p&gt;&lt;p&gt;invoker = (CreateInstanceInvoker)method.CreateDelegate(typeof(CreateInstanceInvoker));&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Definisce un metodo senza parametri, ma con tipo di ritorno Object, ed emette due istruzioni: la newobj che crea l'istanza del tipo e mette nello stack il puntatore, mentre ret lo estrae dallo stack e lo restituisce al chiamante.&lt;/p&gt;&lt;p&gt;Ho trovato interessante questi internal perch&#233; piuttosto importanti e perch&#233; fanno capire meglio LINQ. Nel prossimo post mostrer&#242; l'implementazione di FastSetValue e un FastSetValues che permette di valorizzare pi&#249; propriet&#224; contemporaneamente guadagnando moltissimo in prestazioni, ovviamente tutto direttamente in IL :-)-&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_2.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2335/LINQ-Reflection.aspx"/><issued>2008-07-19T22:03:00+00:00</issued><modified>2008-07-19T22:03:00+00:00</modified><slash:comments>4</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2335/LINQ-Reflection.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2335.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2335</trackback:ping></entry><entry><title>Reflection: migliorare le performance</title><id>http://blogs.aspitalia.com/ricciolo/post2332/Reflection-Migliorare-Performance.aspx</id><created>2008-07-17T20:34:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2332' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;La reflection &#232; quello strumento che permette di interrogare a runtime i metadati di un assembly, analizzare i tipi, i membri ed invocare dinamicamente metodi, propriet&#224; ed eventi. Il namespace &lt;strong&gt;System.Reflection&lt;/strong&gt; c'&#232; dal .NET Framework 1.0 e l'importanza di questo strumento si &#232; fatta sempre pi&#249; sentire, da una parte perch&#233; il framework &#232; sempre pi&#249; configurabile, dall'altra perch&#233; framework come &lt;strong&gt;NHibernate&lt;/strong&gt;, &lt;strong&gt;Linq to SQL&lt;/strong&gt; o &lt;strong&gt;Entity Framework&lt;/strong&gt; lo pongono al centro di una questione importante: le performance.&lt;/p&gt;&lt;p&gt;Infatti la reflection &#232; lenta. Tanto per dare un'idea con un semplice esempio, se dobbiamo creare un'istanza di una classe possiamo farlo chiamando il costruttore nel canonico modo oppure via reflection:&lt;/p&gt;&lt;p&gt;&lt;code&gt;for (int x = 0; x &amp;lt; max; x++)&lt;br /&gt;&#160; &#160; p = new Product();&lt;/p&gt;&lt;p&gt;Type t = typeof(Product);&lt;br /&gt;for (int x = 0; x &amp;lt; max; x++)&lt;br /&gt;&#160; &#160; p = Activator.CreateInstance(t);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Sulla mia macchina, con 10milioni di iterazioni ottengo questi tempi:&lt;/p&gt;&lt;p&gt;&lt;code&gt;00:00:00.1892963&lt;br /&gt;00:00:01.8751132&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Ci mette ben 10 volte di pi&#249;. Per non parlare di come impostare le propriet&#224;:&lt;/p&gt;&lt;p&gt;&lt;code&gt;for (int x = 0; x &amp;lt; max; x++)&lt;br /&gt;&#160;&#160;&#160; p.Description = &amp;quot;ciao&amp;quot;;&lt;/p&gt;&lt;p&gt;PropertyInfo pi = typeof(Product).GetProperty(&amp;quot;Description&amp;quot;, BindingFlags.Public | BindingFlags.Instance);&lt;br /&gt;for (int x = 0; x &amp;lt; max; x++)&lt;br /&gt;&#160;&#160;&#160; pi.SetValue(p, &amp;quot;ciao&amp;quot;, null);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Escludendo i tempi di ricerca della propriet&#224; con il metodo &lt;strong&gt;GetProperty&lt;/strong&gt;, i dati sono:&lt;/p&gt;&lt;p&gt;&lt;code&gt;00:00:00.1141661&lt;br /&gt;00:00:16.4958957&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Ovviamente questi sono dati indicativi ed &#232; ovvio che il confronto con il codice compilato &#232; ingiusto. Con la reflection abbiamo pi&#249; dinamicit&#224; sui tipi e possiamo creare strumenti come gli ORM citati prima.&lt;/p&gt;&lt;p&gt;Come si possono quindi aumentare le performance? Una possibilit&#224; &#232; quella di generare dinamicamente codice specifico per quel tipo e per certi membri.&#160;Infatti all'interno del namespace &lt;strong&gt;System.Reflection.Emit&lt;/strong&gt; c'&#232; tutto quello che serve per emettere IL al volo godendo delle stesse performance del codice compilato.&lt;br /&gt;Una delle accuse che si fanno a NHibernate o LINQ to SQL &#232; che sono lenti per via della reflection. In realt&#224;, sia il primo (dalla versione v2) che il secondo, tolto il lavoro che fanno inizialmente di analisi delle classi e dei mapping, non usano reflection, ma a regime istanziano e impostano campi e propriet&#224; con IL generato ad hoc. L'overhead semmai risiede nella gestione dei delegate e&#160;nel lavoro di mapping. In fondo se si pretende di lavorare indipendentemente dal database e&#160;instanziare tipi dinamicamente, non si pu&#242; neanche pretendere di non pagare qualcosa per questa ulteriore stratificazione.&lt;/p&gt;&lt;p&gt;Comunque non &#232; delle implementazioni degli ORM che mi interessa parlare, ma bens&#236; di come generare codice IL. Lo mostrer&#242; nel prossimo post dove far&#242; vedere alcuni extension method che usano la System.Reflection.Emit e la classe &lt;strong&gt;LambaExpression&lt;/strong&gt; per velocizzare le operazioni di reflection.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_2.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 2.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2332/Reflection-Migliorare-Performance.aspx"/><issued>2008-07-17T22:34:00+00:00</issued><modified>2008-07-17T22:34:00+00:00</modified><slash:comments>1</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2332/Reflection-Migliorare-Performance.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2332.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2332</trackback:ping></entry><entry><title>Riutilizzare porzioni di espressioni LINQ</title><id>http://blogs.aspitalia.com/ricciolo/post2306/Riutilizzare-Porzioni-Espressioni-LINQ.aspx</id><created>2008-07-04T03:31:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2306' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Se anche voi usate in alcuni progetti &lt;strong&gt;LINQ to SQL&lt;/strong&gt; come &lt;strong&gt;DAL&lt;/strong&gt;, vi troverete un domain model e le classi create tramite il &lt;strong&gt;DBML&lt;/strong&gt;. Questo perch&#233; le prime vengono usate nello strato di presentazione e in quello business, mentre le seconde utilizzate all'interno del DAL realizzato con LINQ to SQL.&lt;br /&gt;Di conseguenza ci ritroviamo a dover mappare le due entit&#224; in modi pi&#249; o meno complessi. Poniamo di avere la classe Customer di LINQ to SQL e quella del domain model (per semplificare con mapping 1:1):&lt;/p&gt;&lt;p&gt;&lt;code&gt;public class CustomerL2S&lt;br /&gt;{&lt;br /&gt;   public int ID { get; set; }&lt;br /&gt;   public string Description { get; set; }&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;public class Customer&lt;br /&gt;{&lt;br /&gt;   public int ID { get; set; }&lt;br /&gt;   public string Description { get; set; }&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In un ipotetico metodo GetSingle che dato l'ID ti d&#224; l'entit&#224;, scriviamo qualcosa del genere:&lt;/p&gt;&lt;p&gt;&lt;code&gt;var customer = from c in customers&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;where c.ID == 1&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;select new Customer&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ID = c.ID,&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Description = c.Description&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;};&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Poi magari un metodo di List restituisce tutti i Customer, senza filtrarli e purtroppo ci tocca duplicare l'intera query, compreso tutto il mapping, senza la clausola where. Potremmo essere tentati di fare una funzione, cos&#236;:&lt;/p&gt;&lt;p&gt;&lt;code&gt;var customer = from c in customers&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;where c.ID == 1&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;select GetCustomer(c);&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Purtroppo questa tecnica non funziona, perch&#233; passiamo una funzione managed al motore di LINQ to SQL che non pu&#242; passarla a SQL Server. Il problema non sta nella funzione, ma in ci&#242; che essa fa. Infatti la soluzione sta nel lavorare sempre a livello di expression tree. Potremmo infatti creare un extension method (solo per comodit&#224; nella chiamata) specifico per il Customer che effettua il mapping che ci permetta di riutilizzarlo pi&#249; volte:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static class Extentions&lt;br /&gt;{&lt;br /&gt;   public static IQueryable&amp;lt;Customer&amp;gt; SelectToCustomer(this IQueryable&amp;lt;CustomerL2S&amp;gt; source)&lt;br /&gt;   {&lt;br /&gt; &amp;nbsp; &amp;nbsp;   return source.Select(c =&amp;gt; new Customer&lt;br /&gt; &amp;nbsp; &amp;nbsp;   {&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;   ID = c.ID,&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;   Description = c.Description&lt;br /&gt; &amp;nbsp; &amp;nbsp;   });&lt;br /&gt;   }&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Nella funzione accettiamo un IQueryable specifico per l'entit&#224; CustomerL2S e sfruttando l'extension method select effettuamo il mapping, ma sempre a livello di espressione, consentendola di portarla su SQL Server. L'utilizzo poi &#232; semplice:&lt;/p&gt;&lt;p&gt;&lt;code&gt;var customer = (from c in customers&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;   where c.ID == 1&lt;br /&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;   select c).SelectToCustomer();&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Il doppio select &#232; d'obbligo per via della query syntax, ma non &#232; un problema poich&#233; la query SQL generata &#232; corretta.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ_to_SQL/&quot; rel=&quot;tag&quot;&gt;LINQ to SQL&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2306/Riutilizzare-Porzioni-Espressioni-LINQ.aspx"/><issued>2008-07-04T05:31:00+00:00</issued><modified>2008-07-04T05:31:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2306/Riutilizzare-Porzioni-Espressioni-LINQ.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2306.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2306</trackback:ping></entry><entry><title>LINQ to SQL: Chiamare extension method non implementati</title><id>http://blogs.aspitalia.com/ricciolo/post2302/LINQ-SQL-Chiamare-Extension-Method-Implementati.aspx</id><created>2008-06-30T16:31:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2302' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Credo che qualcuno si sia gi&#224; imbatutto in un problema dovuto ad una&#160;query&#160;&lt;strong&gt;LINQ to SQL&lt;/strong&gt; simile a questa:&lt;/p&gt;&lt;p&gt;&lt;code&gt;bool MiaFunzione(Customer c)&lt;br /&gt;{&lt;br /&gt;&#160;&#160;&#160; return true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var customer = from c in dc.Customers&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where MiaFunzione(c)&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select c;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Se lo eseguiamo otterremo un exception perch&#233; MiaFunzione &#232; un metodo managed e non pu&#242; essere valutato tramite una query &lt;strong&gt;SQL&lt;/strong&gt;. L'esempio pu&#242; sembrare palese, ma in realt&#224; questo problema&#160;c'&#232; anche con extesion method come Contains o tutti quelli che accettano un &lt;strong&gt;IEqualityComparer&lt;/strong&gt;, non portabile sul SQL Server.&lt;/p&gt;&lt;p&gt;Poich&#233; quando chiamiamo un extension method il compilatore individua il metodo che come argomento vuole il tipo pi&#249; vicino alla variabile, quando interroghiamo dc.Customers, la cui propriet&#224; &#232; di tipo &lt;strong&gt;Table&amp;lt;T&amp;gt;&lt;/strong&gt; che a sua volta implementa &lt;strong&gt;IQueryable&amp;lt;T&amp;gt;,&lt;/strong&gt; andiamo a chiamare i metodi contenuti nella classe &lt;strong&gt;System.Linq.Queryable&lt;/strong&gt; i quali lavorano sull'espressione, per poi essere valuta, trasformata in query SQL ed eseguita,&#160;all'effettivo consumo dell'enumeratore.&lt;br /&gt;Se per&#242; il tipo &#232; &lt;strong&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/strong&gt; andiamo a chiamare i metodi della classe &lt;strong&gt;System.Linq.Enumerable&lt;/strong&gt;, non lavorando pi&#249; sull'espressione, ma aggiungendo nuovi iteratori che valuteranno T ad ogni ciclo.&lt;/p&gt;&lt;p&gt;Di conseguenza, per risolvere i problema basta effettuare un downcast su IEnumerable&amp;lt;T&amp;gt; o meglio ancora l'extesion method &lt;strong&gt;AsEnumerable&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;code&gt;var customer = from c in dc.Customers.AsEnumerable()&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where MiaFunzione(c)&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; select c;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Attenzione per&#242;, cos&#236; facendo l'extension method Where consuma l'intero dc.Customers ottenuto da SQL Server, di conseguenza viene scaricata l'intera tabella dal DB per poi essere filtrata con LINQ to Object. Il alcuni casi potrebbe andare bene, in altri no; basta saperlo.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ_to_SQL/&quot; rel=&quot;tag&quot;&gt;LINQ to SQL&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2302/LINQ-SQL-Chiamare-Extension-Method-Implementati.aspx"/><issued>2008-06-30T18:31:00+00:00</issued><modified>2008-06-30T18:31:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2302/LINQ-SQL-Chiamare-Extension-Method-Implementati.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2302.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2302</trackback:ping></entry><entry><title>Extension method ricorsivo per LINQ</title><id>http://blogs.aspitalia.com/ricciolo/post2298/Extension-Method-Ricorsivo-LINQ.aspx</id><created>2008-06-30T07:12:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2298' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Ultimamente sto giocando parecchio con LINQ e trovo incredibile come possa cambiare il modo di scrivere parti di codice: tutto diventa pi&#249; leggibile e si ha subito l'idea di cosa una query faccia.&lt;/p&gt;&lt;p&gt;Oggi dovevo sfogliare tutte le sezioni di configurazioni e per ognuna chiamare il metodo ProtectSection per criptarla. Siccome ogni gruppo di configurazione ha delle sezioni e a sua volta dei sotto gruppi di configurazione, dovevo fare una funzione da richiamare in modo ricorsivo per ogni gruppo, ma non mi piaceva. La domanda che ormai mi pongo &#232;: si pu&#242; fare in LINQ? In questo caso no o almeno io non ho trovato un extension method o una combinazione di essi che facesse al caso mio. Perci&#242; ne ho creato uno mio generico, per rendere flat una struttura ad albero:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static class Extensions&lt;br /&gt;{&lt;br /&gt;&#160;&#160;public static IEnumerable&lt;t /&gt; ToFlat&lt;t /&gt;(this IEnumerable&lt;t /&gt; source, Func&amp;lt;T, IEnumerable&amp;lt;T&amp;gt;&lt;t, /&gt;&amp;gt; childPredicate)&lt;br /&gt;&#160;&#160;{&lt;br /&gt;&#160;&#160;&#160;&#160;foreach (T t in source)&lt;br /&gt;&#160;&#160;&#160;&#160;{&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;yield return t;&lt;/p&gt;&lt;p&gt;&#160;&#160;&#160;&#160;&#160;&#160;IEnumerable&lt;t /&gt; children = childPredicate(t);&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;foreach (T child in ToFlat(children, childPredicate))&lt;br /&gt;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;yield return child;&lt;br /&gt;&#160;&#160;&#160;&#160;}&lt;br /&gt;&#160;&#160;}&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In pratica, prende una lista e la sfoglia restituendo ogni elemento della lista stessa. Poi attraverso un predicato ottiene i figli di ogni elemento e per ognuno chiama ricorsivamente la funzione. In questo modo si ottiene un enumeratore piatto che sfoglia tutti gli elementi di una struttura ad al albero.&lt;/p&gt;&lt;p&gt;L'utilizzo poi &#232; banale. Per esempio per sfogliare tutti i controlli di una pagina (il cast serve perch&#233; ControlsCollection non implementa IEnumerable&lt;t /&gt;):&lt;/p&gt;&lt;p&gt;&lt;code&gt;var allControls = this.Controls.Cast&lt;control /&gt;().ToFlat(c =&amp;gt; c.Controls)&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Semplice ed efficace, vero?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2298/Extension-Method-Ricorsivo-LINQ.aspx"/><issued>2008-06-30T09:12:00+00:00</issued><modified>2008-06-30T09:12:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2298/Extension-Method-Ricorsivo-LINQ.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2298.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2298</trackback:ping></entry><entry><title>Uso improprio dei generics</title><id>http://blogs.aspitalia.com/ricciolo/post2301/Uso-Improprio-Generics.aspx</id><created>2008-06-28T15:56:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2301' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;I generics sono tanto belli bellini. Senza di essi non esisterebbe &lt;strong&gt;LINQ&lt;/strong&gt;,&#160;gli extension method non avrebbero trovato cos&#236; ampio spazio e non potremmo scrivere classi generiche utilizzabili per pi&#249; tipi.&lt;/p&gt;&lt;p&gt;Ci sono alcune pratiche per&#242; che&#160;mi capitano di vedere e io non ritengo corrette. Per esempio capita di vedere metodi che accettano un tipo generico ed effettuano un cast al loro interno, celandolo al chiamante:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static T GetValue&amp;lt;T&amp;gt;()&lt;br /&gt;{&lt;br /&gt;&#160;&#160;&#160; object obj = ....;&lt;br /&gt;&#160;&#160;&#160; return (T)obj;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;L'esempio &#232; banale, ma sufficiente per illustrare il mio dubbio. I generics son nati per tipizzare e migliorare anche in performance (evitano cast e box/unbox). Nel passato si usava un ArrayList e la cosa principalmente brutta era non avere una tipizzazione e si rischiava di cadere in &lt;strong&gt;InvalidCastException&lt;/strong&gt;. Con i generics questo problema &#232; stato risolto. Ci&#242; che non mi piace del codice precedente &#232; che celiamo al chiamante il fatto che io faccio un cast e per chi usa questo metodo sembra tutto sicuro e tipizzato.&lt;br /&gt;In &lt;strong&gt;LINQ to DataSet&lt;/strong&gt; hanno messo l'extesion method &lt;strong&gt;Field&amp;lt;T&amp;gt;&lt;/strong&gt; che data la colonna ti restituisce il valore tipizzato, cos&#236;:&lt;/p&gt;&lt;p&gt;&lt;code&gt;int c = row.Field&amp;lt;int&amp;gt;(&amp;quot;colonna&amp;quot;)&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Qual'&#232; la differenza rispetto a quest'altro codice?&lt;/p&gt;&lt;p&gt;&lt;code&gt;int c = (int)row[&amp;quot;colonna&amp;quot;]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Di fatto nessuna. Entrambi sono potenzialmente vittime di un InvalidCastException, solo che il primo codice &#232; stilisticamente pi&#249; bello da vedere. Non trovate? Ormai avere un cast nel codice &#232; come avere qualcosa di sporco e infatti nella maggior parte dei casi secondo me &#232; cos&#236;. Con l'extension method generic hanno reso pi&#249; bello il codice, ma di fatto il problema resta.&lt;br /&gt;E' vero che nella documentazione c'&#232; giustamente scritto che tra le probabili eccezioni c'&#232; tale eccezione, ma a questo punto allora mi domando: perch&#233; implementare un metodo del genere?&lt;/p&gt;&lt;p&gt;Viceversa trovo molto bello l'uso dei metodi generic per effettuare downcast. Per esempio:&lt;/p&gt;&lt;p&gt;&lt;code&gt;public static IEnumerable&amp;lt;TSource&amp;gt; AsEnumerable&amp;lt;TSource&amp;gt;(this IEnumerable&amp;lt;TSource&amp;gt; source)&lt;br /&gt;{&lt;br /&gt;&#160;&#160;&#160; return source;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In questo caso non viene coinvolto nessun cast, cosa che dovrei usare (seppure in modo sicuro) se non avessi questo metodo, ma semplicemente diciamo al compilatore su che tipo riferirsi se poi eventualmente chiamiamo altri metodi.&lt;/p&gt;&lt;p&gt;Ok, ci sono problemi ben pi&#249; seri nella vita, ma comunque rendo pubblica questa mia riflessione.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/LINQ/&quot; rel=&quot;tag&quot;&gt;LINQ&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2301/Uso-Improprio-Generics.aspx"/><issued>2008-06-28T17:56:00+00:00</issued><modified>2008-06-28T17:56:00+00:00</modified><slash:comments>1</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2301/Uso-Improprio-Generics.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2301.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2301</trackback:ping></entry><entry><title>Le novit&amp;#224; di WPF 3.5 nel service pack 1</title><id>http://blogs.aspitalia.com/ricciolo/post2284/Novita-WPF-3.5-Service-Pack.aspx</id><created>2008-05-13T17:56:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2284' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Come &lt;a href=&quot;http://www.aspitalia.com/focuson/1038/Beta-Pubblica-SP1-.NET-Framework-3.5-2008.aspx&quot;&gt;sappiamo&lt;/a&gt; &#232; in corso lo sviluppo del service pack 1 del &lt;strong&gt;.NET Framework 3.5&lt;/strong&gt; e anche WPF non immune da nuove funzionalit&#224;.&lt;/p&gt;&lt;p&gt;Cominciamo dai controlli che si arricchiscono dei nuovi &lt;strong&gt;DataGrid&lt;/strong&gt;, &lt;strong&gt;WebBrowser&lt;/strong&gt; e in futuro anche di &lt;strong&gt;Office Ribbon&lt;/strong&gt;. Il primo, fortemente richiesto, supporta&#160;modifiche in place&#160;transazionali, ordinamento, multi selezione, validazione e la virtualizzazione delle righe e delle colonne&#160;come gi&#224; avviene, per esempio,&#160;per la ListBox. Il WebBrowser invece, in alternativa al Frame, permette di accedere al DOM della pagina, avere un maggior controllo del componenti IE&#160;e&#160;consente di&#160;incorporare anche applicazioni in &lt;strong&gt;Silverlight&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Ai nuovi controlli si aggiungono piccoli ritocchi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;supporto StringFormat nelle espressioni di &lt;strong&gt;Binding&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;template per righe alternate negli &lt;strong&gt;ItemsControl&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;la virtualizzazione delle righe per gli ItemsControl pu&#242; ora reciclare (attached property VirtualizationMode)&#160;gli elementi non pi&#249; visibile e permettere lo scrolling e relativa creazione degli elementi&#160;solo quando l'utente rilascia il mouse (attached property IsDeferredScrollingEnabled), cos&#236; da risparmiare memoria. Anche la &lt;strong&gt;TreeView&lt;/strong&gt; supporta ora la virtualizzazione degli elementi.&#160;Per maggiori informazioni sull'attuale funzionamento &#232; disponibile &lt;a href=&quot;http://www.winfxitalia.com/articoli/presentation-foundation/controlli-elenco-WPF.aspx&quot;&gt;questo articolo&lt;/a&gt;;&lt;/li&gt;&lt;li&gt;nuova interfaccia &lt;strong&gt;IEditableCollectionView&lt;/strong&gt; per intervenire tramite viste sulle sorgenti dati;&lt;/li&gt;&lt;li&gt;supporto al binding con sorgenti Linq To Sql e Linq To Entities migliorando inoltre le performance con &lt;strong&gt;IEnumerable&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;miglioramenti di performance nel rendering di testo, nella grafica 2D e nella classe &lt;strong&gt;WriteableBitmap&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;alla propriet&#224; &lt;strong&gt;BitmapEffect&lt;/strong&gt; si affianca Effect che a differenza dell'altra permette di utilizzare effetti come blur e shadow mediante l'accelarazione grafica e sfruttando le capacit&#224; di pixel shader delle GPU, rendendolo di fatto di gran lunga pi&#249; performance rispetto all'elaborazioni bitmap basate su CPU;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A tutto questo non mancano miglioramenti all'ambiente di sviluppo in &lt;strong&gt;Visual Studio 2008&lt;/strong&gt;, costituiti da un completo supporto agli eventi e agli style, al refactoring e references&#160;degli elementi, ad una migliore segnalazione&#160;dei problemi&#160;in caso di eventuali errori&#160;a runtime&#160;nel markup, non rilevati in fase di compilazione.&lt;/p&gt;&lt;p&gt;Per ultimo vi sono novit&#224; sul fronte client (quindi anche WinForms) e al deployment degli applicativi. E' prevista una nuova modalit&#224; &amp;quot;&lt;strong&gt;Client profile&lt;/strong&gt;&amp;quot; che consente di distribuire l'applicativo richiedendo solo un sotto insieme degli assembly contenuti nel framework escludendo quelli che trovano utilit&#224; solo in applicazione server, come per esempio la parte di ASP.NET, riducendo il setup a circa 20MB (rispetto a 270MB totali).&lt;br /&gt;Ad esso si unisce un piccolo bootstrapper, compatibile con &lt;strong&gt;ClickOnce&lt;/strong&gt; (interfaccia ora&#160; personalizzabile), che si occupa di installare l'intero .NET Framework 3.5 o se richiesto solo il sotto insieme client e in un secondo momento, se richiesto da un'ulteriore applicazione, di installare il restante Framework.&#160;&#160;Anche Visual Studio 2008 supporta questa modalit&#224; e presenta degli errori in fase di compilazione nel caso dovessimo usare assembly non presenti nel Framework ridotto.&lt;/p&gt;&lt;p&gt;Non ci sono eclatanti novit&#224; a dimostrazione del fatto che gi&#224; WPF nella sua prima versione era gi&#224; un ottimo framework, ma devo dire che mi soddisfano. Forse resta l'ambiente di sviluppo ancora un po' indietro e manca ancora di molte funzionalit&#224;, ma a piccoli passi forse ce la faremo :-)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Visual_Studio/&quot; rel=&quot;tag&quot;&gt;Visual Studio&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Windows_Presentation_Foundation/&quot; rel=&quot;tag&quot;&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2284/Novita-WPF-3.5-Service-Pack.aspx"/><issued>2008-05-13T19:56:00+00:00</issued><modified>2008-05-13T19:56:00+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2284/Novita-WPF-3.5-Service-Pack.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2284.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2284</trackback:ping></entry><entry><title>Styles Explorer: decompilatore BAML</title><id>http://blogs.aspitalia.com/ricciolo/post2263/Styles-Explorer-Decompilatore-BAML.aspx</id><created>2008-04-04T21:57:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2263' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Vi ricordate quando vi &lt;a href=&quot;http://blogs.aspitalia.com/ricciolo/post2124/Come-Fatto-Formato-BAML-WPF.aspx&quot;&gt;parlai&lt;/a&gt; di come viene compilato lo &lt;strong&gt;XAML&lt;/strong&gt; e quale struttura ha? Beh &#232; un po' che avevo pi&#249; o meno pronta quella classe e mancava qualcosa per usarla a dovere. Portando avanti a singhiozzo il progetto, finalmente posso farvi vedere qualcosa di &lt;strong&gt;Styles Explorer&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;E' uno strumento che ti permette di aprire qualsiasi DLL, enumerare le risorse &lt;strong&gt;BAML&lt;/strong&gt; che contiene e decompilare (se ce la fa) fornendo l'XML. E' principalmente improntato sui &lt;strong&gt;ResourceDictionary&lt;/strong&gt;, perci&#242; &#232; in grado di fornire un'anteprima di un oggetto o di uno style.&lt;/p&gt;&lt;p&gt;Siccome i tempi cambiano, invece degli screenshot vi metto un bel filmato&lt;/p&gt;&lt;embed pluginspage=&quot;http://macromedia.com/go/getflashplayer&quot; src=&quot;http://images.video.msn.com/flash/soapbox1_1.swf&quot; width=&quot;432&quot; height=&quot;364&quot; type=&quot;application/x-shockwave-flash&quot; flashvars=&quot;c=v&amp;amp;v=184a6290-13ec-4aa3-8c37-51e85d430303&amp;amp;ifs=true&amp;amp;fr=msnvideo&amp;amp;mkt=en-US&amp;amp;brand=&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; base=&quot;http://images.video.msn.com&quot; quality=&quot;high&quot; /&gt;&lt;/embed /&gt;&lt;br /&gt;&lt;a title=&quot;Styles Explorer&quot; href=&quot;http://video.msn.com/video.aspx?vid=184a6290-13ec-4aa3-8c37-51e85d430303&quot; target=&quot;_new&quot;&gt;Video: Styles Explorer&lt;/a&gt;&lt;p&gt;Ovviamente il progetto &#232; ancora in corso e va migliorato, ma fino adesso mi son divertito a fare alcune cose carine, come usare pi&#249; AppDomain per isolare il caricamento degli assembly, o fare una nuova message pump solo per la preview cos&#236; da evitare problemi con il resto dell'applicazione.&lt;/p&gt;&lt;p&gt;Ah dimenticavo, potete installarlo da &lt;a href=&quot;http://ricciolo.lab.aspitalia.com/StylesExplorer/Ricciolo.StylesExplorer.application&quot;&gt;qua&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Windows_Presentation_Foundation/&quot; rel=&quot;tag&quot;&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2263/Styles-Explorer-Decompilatore-BAML.aspx"/><issued>2008-04-04T23:57:00+00:00</issued><modified>2008-04-04T23:57:00+00:00</modified><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2263/Styles-Explorer-Decompilatore-BAML.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2263.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2263</trackback:ping></entry><entry><title>Le evoluzioni del Web che non capisco</title><id>http://blogs.aspitalia.com/ricciolo/post2256/Evoluzioni-Web-Capisco.aspx</id><created>2008-03-18T16:51:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2256' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Chi mi conosce sa che non sono un gran simpatizzante di &lt;strong&gt;AJAX&lt;/strong&gt; e riconoscendo che in effetti serve qualcosa di pi&#249; del buon vecchio HTML, trovo Silverlight decisamente una soluzione migliore. Ma non &#232; di questa moda che voglio parlare, ma bens&#236; di &lt;strong&gt;REST&lt;/strong&gt; e &lt;strong&gt;POX&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Con il primo termine si intende il voler sfruttare a pieno le capacit&#224; di &lt;strong&gt;HTTP&lt;/strong&gt;, mediante i suoi method, per ampliare l'applicazione web e fornire servizi aggiuntivi usufruibili al di fuori dell'HTML e della semplice navigazione. In pratica, siccome esistono i metodi &lt;strong&gt;GET&lt;/strong&gt;, &lt;strong&gt;POST&lt;/strong&gt;, &lt;strong&gt;PUT&lt;/strong&gt; e &lt;strong&gt;DELETE&lt;/strong&gt; si &#232; pensato di sfruttarli per eseguire le classiche operazioni CRUD, magari aggiugendo dei parametri nell'URI o nel contenuto della richiesta. Tutto questo ovviamente esiste da sempre, ma veniva marginalmente sfruttato e solo ora, e ben venga, siti come Amazon, Google, Live, ecc permettono di interrogare e di usufruire dei loro servizi mediante REST.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;POX&lt;/strong&gt; invece vuol dire Plain Old XML e in pratica vuol dire usare XML semplice senza fronzoli, da utilizzare nelle richieste o risposte REST.&lt;/p&gt;&lt;p&gt;Cosa non mi piace di tutto questo? Il fatto che si sta reinventando la ruota. Per esempio, chi espone operazioni REST si trova a dover fornire della documentazione per spiegare come chiamare le varie operazioni, come dev'essere passato l'XML e spesso in maniera superficiale, limitandosi ad un esempio di XML o ad un esempio di parametro in query string. Beh a tutto questo qualcuno ci aveva gi&#224; pensato e vedendo che non era sufficiente aveva pensato ai &lt;strong&gt;WebService&lt;/strong&gt;, a &lt;strong&gt;SOAP&lt;/strong&gt;, ai consorzi per renderli i pi&#249; interoperabili possibili. Per XML esistono gli schema &lt;strong&gt;XSD&lt;/strong&gt; che sono molto pi&#249; completi, mentre per conoscere quali operazioni espone un servizio c'&#232; &lt;strong&gt;WSDL&lt;/strong&gt; e &lt;strong&gt;WS-Metadata Exchange&lt;/strong&gt;. Senza contare che con framework come &lt;strong&gt;WCF&lt;/strong&gt; basta semplicemente fare un &amp;quot;Add Service reference&amp;quot; e ci si pu&#242; persino permettere di ignorare questi linguaggi e di esporre della documentazione aggiuntiva.&lt;/p&gt;&lt;p&gt;E' vero che non tutti fanno applicazioni enterprise ed usare WCF/WebService pu&#242; sembrare un carro armato per uccidere le mosche, ma sono del parere che alcune problematiche sono presenti anche in semplici siti web. Tra questi il gi&#224; citato, come chiamare un'operazione, ma anche quali errori mi pu&#242; eventualmente dare e come li gestisco. Poi man mano ci sono altri aspetti, come l'autenticazione, spesso affidata ad un token rilasciato da chi espone il servizio da inserire nella querystring, mentre in &lt;strong&gt;WS-*&lt;/strong&gt; tutto questo &#232; gi&#224; definito. Sono inoltre definiti come rendere le operazioni sicure, criptate, transazionali, come gestire le policy ed inviare file di grosse dimensioni. Ovviamente se tutto questo non serve basta non abilitarlo e l'XML resta contenuto, senza offenderlo chiamandolo POX :-).&lt;/p&gt;&lt;p&gt;E' per questo che storto un po' il naso e che il diffondersi di questi termini sia pi&#249; dovuto o ad ignoranza su certe tecnologie (almeno io so il loro nome :-) ) oppure ad una pigrizia nell'affrontarle ed impararle. Detto questo, sicuramente ci sono ambiti in cui una normale richiesta GET basta e avanza; l'importante che vengano valutate anche le altre strade e che non venga coniato qualche nuovo termine o nuova era del web.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/Silverlight/&quot; rel=&quot;tag&quot;&gt;Silverlight&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2256/Evoluzioni-Web-Capisco.aspx"/><issued>2008-03-18T17:51:00+00:00</issued><modified>2008-03-18T17:51:00+00:00</modified><slash:comments>11</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2256/Evoluzioni-Web-Capisco.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2256.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2256</trackback:ping></entry><entry><title>Un'occhiata a Silverlight 2.0</title><id>http://blogs.aspitalia.com/ricciolo/post2248/Unocchiata-Silverlight-2.0.aspx</id><created>2008-03-08T16:29:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2248' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Come probabilmente &lt;a href=&quot;http://www.aspitalia.com/focuson/1027/Rilasciata-Ufficialmente-Versione-Beta1-Silverlight-2.0.aspx&quot;&gt;saprete&lt;/a&gt; &#232; stata rilasciata la beta &lt;strong&gt;Silverlight 2.0&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Ovviamente da fan di &lt;strong&gt;WPF&lt;/strong&gt; non ho resistito dal provarla subito. Sinceramente, delle scorse preview ero rimasto un po' deluso, poich&#233; conoscendo WPF mi rendevo conto di quante cose mancassero diventando cos&#236; frustrante giocarci. Beh invece con Silverlight 2.0 mi ritengo soddisfatto e entusiasta come un bambino che scarta i regali a Natale :-D&lt;/p&gt;&lt;p&gt;Per prima cosa il setup installa runtime, template per &lt;strong&gt;Visual Studio 2008&lt;/strong&gt; e SDK. Una parte del SDK &#232; rivolta al server e l'altra al client.&lt;/p&gt;&lt;p&gt;Lato server una nuova System.Web.Silverlight.dll contiene i controlli &lt;strong&gt;Silverlight&lt;/strong&gt; e &lt;strong&gt;MediaPlayer&lt;/strong&gt;. Il primo semplicemente crea il markup per istanziare il plugin, include il codice JavaScript e non &#232; pi&#249; necessario includere script esterni ecc. MediaPlayer &#232; un&#160;controllo pi&#249; evoluto che permette con due click di inserire un player di video con tanto di&#160;marcatori e capitoli basandosi su&#160;Silverlight. Il tutto completamente skinnabile, con&#160;una decina di skin gi&#224; presenti nel SDK. Molto maschio.&lt;/p&gt;&lt;p&gt;Lato client l'architettura &#232;&#160;rimasta invariata e il runtime, di soli 4,3MB,&#160;&#232;&#160;installato in %ProgramFiles%\Microsoft Silverlight\2.0.30226.2. Rispetto alla alpha abbiamo in pi&#249; System.ServiceModel (WCF quindi) con &lt;strong&gt;BasicHttpBinding&lt;/strong&gt;, supporto a &lt;strong&gt;REST&lt;/strong&gt; e&#160;&lt;strong&gt;JSON&lt;/strong&gt;. L'assembly System.Windows &#232; stato ampliato con altre classi base con niente popo di meno che: StackPanel, Grid, Border, TextBox, ItemsControl (i principali).&lt;/p&gt;&lt;p&gt;Incredibile, c'&#232; la classe &lt;strong&gt;Binding&lt;/strong&gt; con IValueConverter, BindingMode, Source, ma nessun altra tipologia di binding. In molti aspetti Silverlight assomiglia da fuori a WPF, ma dentro l'implementazione &#232; decisamente diversa, tendente al risparmio (non poteva essere diversamente). I controlli sono basati su &lt;strong&gt;DependencyProperty&lt;/strong&gt; (anche Attached Property), ma non &#232; presente&#160;nessun meccanismo di triggering o metadati aggiuntivi, mentre gli eventi invece sono quelli normali del CLR; quindi niente Attached Event, niente bubbling o tunneling ed eventi di preview.&lt;/p&gt;&lt;p&gt;I controlli si basano su &lt;strong&gt;Template&lt;/strong&gt; che vengono caricati tramite &lt;strong&gt;Style&lt;/strong&gt; avente come TargetType il tipo del controllo da personalizzare. Gli Style non hanno trigger, quindi nel metodo &lt;strong&gt;ApplyTemplate&lt;/strong&gt; ogni controllo cerca elementi nel template dal nome prefissato&#160;(es: RootElement), ne intercettono gli eventi e interagiscono in base a quest'ultimi. Questa tecnica esiste in modo identico anche in WPF, ma si usa raramente preferendo l'uso di trigger in modo da legare il meno possibile il codice al markup. Continuando con il paragone con WPF, niente Command, CollectionView e WeakEvent.&lt;/p&gt;&lt;p&gt;Tutto sommato quindi, le cose che si potevano implementare sono state copiate da WPF e questo non pu&#242; farmi che piacere&#160;:-), ma ovviamente per non esagerare nella dimensione degli assembly &#232; stato sacrificato qualcosa.&lt;/p&gt;&lt;p&gt;Da Visual Studio o Blend 2.5 possiamo creare un progetto Silverlight 2.0 e rispetto a prima, si sviluppa una specie di class library avente gi&#224; pronti i file App.xaml, che &#232; l'entry point, e un file Page.xaml: lo &lt;strong&gt;UserControl&lt;/strong&gt; principale. Ovviamente hanno il relativo code-behind dove possiamo scrivere in C# 3.0 o VB 9.&lt;br /&gt;Il risultato della compilazione &#232; un file &lt;strong&gt;.xap&lt;/strong&gt;, l'unico file da distribuire,&#160;che&#160;&#232; un file .zip contenente un file di metadati,&#160;i file che abbiamo incluso nel progetto con target Content e&#160;la nostra dll compilata. Quest'ultima contiene nelle risorse i file XAML, ma non compilati in &lt;strong&gt;BAML&lt;/strong&gt; (diversamente da WPF). Probabilmente questa scelta &#232; dovuta al fatto che l'ottimizzazione di caricamento del markup &#232; stata ritenuta sacrificabile, mentre la compressione &#232; gi&#224; ottenuta grazie allo ZIP.&lt;/p&gt;&lt;p&gt;Per ultimo una cosa inaspettata: nel progetto di Visual Studio troveremo referenziati altre dll che verranno poi incluse nel file xap. Queste&#160;normalmetne sono: &lt;strong&gt;System.Windows.Controls&lt;/strong&gt; e &lt;strong&gt;System.Windows.Controls.Extended&lt;/strong&gt;. Queste dll, pi&#249; altre,&#160;si trovano normalmente nella cartella del SDK (C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client) e non sono incluse nel setup di Silverlight. Peccato che quest'altre 18 dll contengano: &lt;strong&gt;Ruby&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, &lt;strong&gt;Managed JScript&lt;/strong&gt;, le classi Syndacation RSS/Atom di WCF, &lt;strong&gt;Linq To Xml&lt;/strong&gt;, controlli come Thumb (per il drag&amp;amp;drop), Button, CheckBox, ListBox, RadioButton, Slider, ScrollBar, ScrollViewer, ToolTip, ToggleButton, DataGrid, Calendar, DateTimePicker, GridSplitter, WatermarkedTextBox.&lt;/p&gt;&lt;p&gt;Prima di tutto stupisce che ci siano controlli che WPF non&#160;ha e sia Silverlight il primo ad implementarli, ma soprattutto ecco spiegato perch&#233; il runtime &#232; piccolo. Infatti tutte le altre dll le mandiamo noi all'utente inglobandole nel file xap. Cos&#236; l'installazione del plugin&#160;&#232; piccola,&#160;mentre l'utente navigando su pi&#249; siti si ritrova a scaricare solo le dll che effettivamente l'applicazione usa, con il rischio ovviamente di scaricare&#160;pi&#249; volte la stessa dll in pacchetti diversi. Furbini vero? :-D&lt;/p&gt;&lt;p&gt;Non l'ho ancora guardato benissimo, ma Silverlight cos&#236; mi piace decisamente e non ha rivali sul web. Se volete vederlo all'opera potete venire al &lt;a href=&quot;http://www.aspitalia.com/eventi/12/Real-Code-Launch-2008-Roma.aspx&quot;&gt;Real Code Launch&lt;/a&gt; che terremo a Roma. Dovete assolutamente venire; chi c'&#232;, c'&#232;, chi non c'&#232;... eh non c'&#232;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Microsoft_Expression/&quot; rel=&quot;tag&quot;&gt;Microsoft Expression&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Silverlight/&quot; rel=&quot;tag&quot;&gt;Silverlight&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Silverlight_-_animazioni/&quot; rel=&quot;tag&quot;&gt;Silverlight - animazioni&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Silverlight_2.0/&quot; rel=&quot;tag&quot;&gt;Silverlight 2.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Windows_Presentation_Foundation/&quot; rel=&quot;tag&quot;&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2248/Unocchiata-Silverlight-2.0.aspx"/><issued>2008-03-08T17:29:00+00:00</issued><modified>2008-03-08T17:29:00+00:00</modified><slash:comments>4</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2248/Unocchiata-Silverlight-2.0.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2248.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2248</trackback:ping></entry><entry><title>Ho aperto un nuovo blog</title><id>http://blogs.aspitalia.com/ricciolo/post2227/Aperto-Blog.aspx</id><created>2008-02-16T17:34:00+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2227' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;Probabilmente vi domanderete perch&#233; abbia aperto un altro blog visto che a mala pena scrivo su questo. Semplice, per scrivere le mie esperienze in inglese. Quindi niente paura, le tematiche sono le stesse e&#160;se sfortunatamente leggete gi&#224; questo blog resterete sempre aggiornati:&#160;tutto quello che scriver&#242; in inglese verr&#224; scritto in italiano e forse anche viceversa.&lt;/p&gt;&lt;p&gt;Il blog si trova &lt;a href=&quot;http://blogs.windowsclient.net/RiccioloCristian/&quot;&gt;qua&lt;/a&gt;, aggregato sul sito di &lt;a href=&quot;http://www.windowsclient.net&quot; target=&quot;_blank&quot;&gt;windowsclient.net&lt;/a&gt;.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2227/Aperto-Blog.aspx"/><issued>2008-02-16T18:34:00+00:00</issued><modified>2008-02-16T18:34:00+00:00</modified><slash:comments>2</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2227/Aperto-Blog.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2227.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2227</trackback:ping></entry><entry><title>DirectShow e WPF: soluzione finale</title><id>http://blogs.aspitalia.com/ricciolo/post2213/DirectShow-WPF-Soluzione-Finale.aspx</id><created>2008-01-28T16:20:37+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2213' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;o quasi... :-) Nel precedente &lt;a href=&quot;http://blogs.aspitalia.com/ricciolo/post2210/sorgenti-custom-mediaelement-wpf.aspx&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;post&lt;/a&gt; ho parlato delle problematiche e possibili soluzioni per mostrare sorgenti video personalizzate in &lt;strong&gt;WPF&lt;/strong&gt;. Ho accennato ad una possibile terza soluzione e sebbene non perfetta la reputo la migliore.&lt;/p&gt; &lt;p&gt;Partiamo dal risultato. Nella figura sottostante potete ammirare un esemplare maschio homo sapiens sapiens:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/ricciolo/directshowewpfsoluzionefinale_10201/camera_2.jpg&quot;&gt;&lt;img height=&quot;466&quot; alt=&quot;camera&quot; src=&quot;http://blogs.aspitalia.com/img/ricciolo/directshowewpfsoluzionefinale_10201/camera_thumb.jpg&quot; width=&quot;404&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;L'esempio &amp;#232; ottenuto usando come VisualBrush di un cubo 3D, un mio oggetto:&lt;/p&gt; &lt;p class=&quot;codebox&quot;&gt;&lt;code&gt;&amp;lt;ricciolo:WebcamElement Source=&amp;quot;webcam://WebcamElement/Video%20Camera&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;Questa classe eredita da una classe base &lt;strong&gt;AdvancedMediaElement&lt;/strong&gt; (eredita dalla standard MediaElement) che offre le funzionalit&amp;#224; base per supportare qualsiasi grafo &lt;strong&gt;DirectShow&lt;/strong&gt;. Nello specifico, per l'intera applicazione uso una libreria Microsoft di nome &lt;a href=&quot;http://research.microsoft.com/sn/detours/&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;detours&lt;/a&gt; che permette di sovrascrivere le funzioni &lt;strong&gt;Win32&lt;/strong&gt; ed eventualmente chiamare la funzione originale. Per il mio scopo intercetto la chiamata a &lt;strong&gt;CoCreateInstance&lt;/strong&gt;, usata per instanziare gli oggetti &lt;strong&gt;COM&lt;/strong&gt;, e quando il MediaElement carica l'URL coercizzo il valore ad un file fisico vuoto creato al volo nella temp dir. &lt;strong&gt;Windows Media Player&lt;/strong&gt; carica DirectShow, crea il grafo e crea l'AsyncReader standard. Io che sono infame, mediante detours, restituisco un mio oggetto che implementa IAsyncReader e non presenta nessun pin. L'intelligent connect passa il nome del file &lt;strong&gt;IFileSourceFilter::Load&lt;/strong&gt; al mio filtro e poi si ferma, mentre quest'ultimo tramite callback notifica all'AdvancedMediaElement di caricare il grafo. Mediante l'associazione URI/istanza chiamo un metodo virtuale OnGraphLoad(IGraphBuilder graph) nella quale le varie implementazioni (nel mio caso WebcamElement) possono popolare il grafo con i fitri che vogliono lavorando via interop con l'ausilio di librerie tipo &lt;a href=&quot;http://directshownet.sourceforge.net/&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;DirectShowLib&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;La soluzione &amp;#232; in parte in C++ CLI, in parte in C#, &amp;#232; aperta ad altre implementazioni e non richiede nessuna registrazione di DLL (le detours sono inglobate nel mio assembly) o di protocol handler. L'unica nota dolente &amp;#232; quel finto file vuoto temporaneo che devo creare per costringere WMP ad usare DirectShow; se qualcune conosce quindi un'alternativa sar&amp;#242; ben contento di ascoltarla.&lt;/p&gt; &lt;p&gt;Presto sorgenti e applicazione di test nel lab&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2213/DirectShow-WPF-Soluzione-Finale.aspx"/><issued>2008-01-28T17:20:37+00:00</issued><modified>2008-01-28T17:20:37+00:00</modified><slash:comments>0</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2213/DirectShow-WPF-Soluzione-Finale.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2213.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2213</trackback:ping></entry><entry><title>Sorgenti custom per MediaElement di WPF</title><id>http://blogs.aspitalia.com/ricciolo/post2210/Sorgenti-Custom-MediaElement-WPF.aspx</id><created>2008-01-23T11:49:59+00:00</created><content type="text/html" mode="escaped">&lt;img src='http://blogs.aspitalia.com/services/counter_rss.aspx?PostID=2210' border=&quot;0&quot; style=&quot;width:1px; height:1px;&quot; /&gt;&lt;p&gt;L'elemento &lt;strong&gt;MediaElement&lt;/strong&gt; &amp;#232; un gran bell'oggettino :-) Permette di mostrare e ascoltare video e audio, il tutto perfettamente integrato con WPF permettendoci di ridimensionarlo come ci pare, usarlo come brush, trasformarlo, applicare trasparenze, ecc...&lt;/p&gt; &lt;p&gt;L'unico problema &amp;#232; che al di l&amp;#224; di file su disco o uri http, non si pu&amp;#242; andare. Per esempio pu&amp;#242; essere utile usare come sorgente la webcam, un tuner TV o una fonte analogica esterna. Per ottenere ci&amp;#242; ci sono vari modi:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Usare l'elemento &lt;strong&gt;HwndSource&lt;/strong&gt; cos&amp;#236; da avere una finestra Win32. Tramite la propriet&amp;#224; Handle abbiamo il suo puntatore e possiamo quindi usare &lt;strong&gt;DirectShow&lt;/strong&gt; effettuando il rendering puntando la finestra con l'interfaccia &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms786984.aspx&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;IVideoWindow&lt;/a&gt;. Se vi interessa &amp;#232; disponibile &lt;a href=&quot;http://directshownet.sourceforge.net/&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;questo progetto&lt;/a&gt; pieno di classi interop per usare DirectShow in .NET. &lt;br /&gt;Questo approccio ha dei limiti dovuti al fatto che HwndSource &amp;#232; s&amp;#236; un elemento WPF, ma poich&amp;#233; contiene al suo interno una nuova finestra Win32 non permette di effettuare trasformazioni, trasparenze, ecc.&lt;/li&gt; &lt;li&gt;Costruire un protocol handler per un proprio schema (esempio webcam://qualcosa) che faccia uso di un source filter personalizzato per DirectShow. Questo &amp;#232; possibile perch&amp;#233; MediaElement utilizza al suo interno &lt;strong&gt;Windows Media Player&lt;/strong&gt; che a sua volta si basa su &lt;strong&gt;Windows Media Foundation&lt;/strong&gt; che a sua volta usa (se necessario) DirectShow.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Ho provato entrambi le modalit&amp;#224; e ovviamente la seconda &amp;#232; la migliore (esiste una terza che sto ancora sperimentando). Nella seconda ho scritto in C++ un source filter che implementa &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms785718.aspx&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;IFileSourceFilter&lt;/a&gt;, cos&amp;#236; da essere da essere chiamato per caricare il mio schema custom. Non entro troppo nei dettagli, ma &amp;#232; compito di WMP caricare il mio filtro e, una volta aggiunto al grafo DirectShow, renderizzare il pin video in uscita sfruttando l'&lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms786503(vs.85).aspx&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;Intelligent Connect&lt;/a&gt;. Questo sistema in pratica si mette a guardare i pin del filtro sorgente e prova le possibili combinazioni tra filtri di decodifica e di rendering fino a quando non riesce a mostrare il video e/o ad emettere il suono. In WPF il filtro sorgente quindi dipende dal protocol handler, mentre il rendering video viene effettuato mediante &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/ms694916(vs.85).aspx&quot; onclick=&quot;blankUrl(this.href); return false;&quot;&gt;Enhanced Video Renderer&lt;/a&gt;: un filtro nuovo e pi&amp;#249; evoluto che permette l'integrazione in WPF.&lt;/p&gt; &lt;p&gt;Nella mia prova ho usato il tipico filtro Ball presente nel SDK, costituito da un pin che restituisce uno stream video che mostra una palla rimbalzare. Una volta pronto il filtro, va poi registrato sia come dll, sia mappando lo schema custom al filtro. Possiamo poi usarlo sia in WMP che in GraphEdit (un tool per testare i filtri). Ecco uno screenshot:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/ricciolo/sorgenticustompermediaelementdiwpf_9079/ball1.png&quot;&gt;&lt;img height=&quot;347&quot; alt=&quot;ball1&quot; src=&quot;http://blogs.aspitalia.com/img/ricciolo/sorgenticustompermediaelementdiwpf_9079/ball1_thumb.png&quot; width=&quot;400&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;A questo punto possiamo usare il filtro anche in WPF:&lt;/p&gt; &lt;p class=&quot;codebox&quot;&gt;&lt;code&gt;&amp;lt;MediaElement Source=&amp;quot;ball://test&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;E questo &amp;#232; il risultato che si ottiene applicandoci il tipico effetto riflesso, per far vedere che possiamo trattare il video come vogliamo:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://blogs.aspitalia.com/img/ricciolo/sorgenticustompermediaelementdiwpf_9079/ball2.png&quot;&gt;&lt;img height=&quot;360&quot; alt=&quot;ball2&quot; src=&quot;http://blogs.aspitalia.com/img/ricciolo/sorgenticustompermediaelementdiwpf_9079/ball2_thumb.png&quot; width=&quot;250&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Quindi in teoria possiamo fare un pin che prenda lo stream da un grafo interno oppure possiamo fare un filtro senza pin, ma che sul metodo Load inserisce nel grafo un nuovo filtro sorgente (webcam, tuner ecc). Ci pensa poi l'intelligent connect ad ignorare il nostro filtro custom, proseguendo sull'altro da noi creato. Questa variante &amp;#232; stilisticamente meno carina, ma pi&amp;#249; semplice.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework/&quot; rel=&quot;tag&quot;&gt;.NET Framework&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.0/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.0&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/.NET_Framework_3.5/&quot; rel=&quot;tag&quot;&gt;.NET Framework 3.5&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/Windows_Presentation_Foundation/&quot; rel=&quot;tag&quot;&gt;Windows Presentation Foundation&lt;/a&gt;, &lt;a href=&quot;http://tags.aspitalia.com/XAML/&quot; rel=&quot;tag&quot;&gt;XAML&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href=&quot;http://www.aspitalia.com/&quot;&gt;(C) 2008 ASPItalia.com Network - All rights reserved&lt;/a&gt;&lt;/p&gt;</content><link rel="alternate" type="text/html" href="http://blogs.aspitalia.com/ricciolo/post2210/Sorgenti-Custom-MediaElement-WPF.aspx"/><issued>2008-01-23T12:49:59+00:00</issued><modified>2008-01-23T12:49:59+00:00</modified><slash:comments>1</slash:comments><wfw:comments>http://blogs.aspitalia.com/ricciolo/post2210/Sorgenti-Custom-MediaElement-WPF.aspx#feedback</wfw:comments><wfw:commentRss>http://blogs.aspitalia.com/ricciolo/CommentRSS2210.aspx</wfw:commentRss><trackback:ping>http://blogs.aspitalia.com/services/trackback.aspx?PostID=2210</trackback:ping></entry></feed>